111C - Petya and Spiders
題意:一開始棋盤上布滿蜘蛛,可以安排每個蜘蛛想鄰近的四個方向走,一秒走一次,問一秒以後空格最多有多少。
做法:暴力枚舉一下每一列蜘蛛的運動方向,可以用狀態壓縮確定每一行的蜘蛛在一秒之後的狀況,這裡值得判斷的是每個狀態是否可以存在假設a,b,c為相鄰的三行
只有當(b|b>>1|b<<1|a|c&(lim-1))==lim,b(>>1<<1是不是很像左右移動)才是可以存在的,不存在的也就是第一行的上一層就只有0這個狀態存在一開始居然沒有
/******看見這麼小的規模,就要想到用狀態壓縮啊。影響最多隻有兩行注意判斷狀態是否存在的方法*********/#include<cstdio>#include<algorithm>#include<cstring>#define eps -1e8using namespace std;const int LMT=1<<6;int dp[45][LMT][LMT],get[LMT],n,m,lim;bool check(int a,int b,int c){ int x=b|(b<<1)|(b>>1)|a|c; return (x&(lim-1))==(lim-1);}int work(int x){ int res,l;res=l=0; do if(x&1)res++; while(x>>=1); return m-res;}void init(void){ for(int i=0;i<=n+1;i++) for(int j=0;j<LMT;j++) for(int k=0;k<LMT;k++) dp[i][j][k]=eps; for(int i=0;i<LMT;i++)get[i]=work(i); for(int i=0;i<lim;i++)dp[0][0][i]=0;}int main(void){ int ans=0; scanf("%d%d",&n,&m); if(n<m) { int t=n;n=m;m=t; } lim=1<<m; init(); for(int i=0;i<n;i++) for(int j=0;j<lim;j++) for(int k=0;k<lim;k++) if(dp[i][j][k]!=eps) for(int l=0;l<lim;l++) if(check(j,k,l))dp[i+1][k][l]=max(dp[i+1][k][l],dp[i][j][k]+get[k]); for(int j=0;j<lim;j++)ans=max(ans,dp[n][j][0]); printf("%d\n",ans); return 0;}
&lim-1失敗