标签:style blog http color os io for art
poj1185:http://poj.org/problem?id=1185
题意:这道题太经典了,看到题目就知道题意,故题意略。
题解:经典的状压dp。以前觉得dp是个很难的东西,做了这一题之后发现,dp其实根本不难,真的,而且很好打。
思维过程:拿到题之后,由于之前做过,所以知道是状压dp。接着想怎么解决。普通的dp,不要考虑障碍,这一题中有障碍限制。多以第一步要处理这个障碍。想到了用这样的方式来解决。把出现h的地方标记为1,其余记0,从右到左,从低位到高位,求出这个数,然后枚举状态的时候,只要把枚举的状态,和这个数&,如果出现1则是不满足的,说明有炮兵出现在H上。好了,障碍解决了。接下来可以dp。一开始想到的是用二维的,发现打出的结果不对,检查一一下,貌似转移不太对。于是,就考虑三维的了。一下子豁然开朗,思路很清晰了。打完之后,过了样例,接着交了,结果wa。不知道错在哪里,就看了discuss。其实这是不对的,应该自己思考。其实,这时候,如果找不出来错误,应该具几组特例的。会发现 11 p,就不对,然后就知道错在哪里,一开始我是第一行初始化dp[i][0],但是最后的结果却是从1开始枚举,所以如果样例只有1,2行的话,答案就不对了。于是,改改,交了,就过了。这里还有一个问题,就是,dp[][i][j],记录的是第i个状态,不是i所代表的状态,真正的状态是s[i],这样就节省了很多空间,这样开3维的才有可能。接下来,是我的代码。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 int n,m; 7 char mp[102][12]; 8 int state[102]; 9 int ct[1003],num,s[1003]; 10 int dp[102][67][67]; 11 bool isok(int x){ 12 if((x&(x<<1))||(x&(x<<2)))return false; 13 return true; 14 } 15 void solve1(){ 16 for(int i=1;i<=n;i++){ 17 int counts=1,ans=0; 18 for(int j=m;j>=1;j--){ 19 if(mp[i][j]==‘H‘) 20 ans+=counts; 21 counts*=2; 22 } 23 state[i]=ans; 24 } 25 } 26 int counts(int x){ 27 int ans=0; 28 while(x){ 29 ans+=(x&1); 30 x/=2; 31 } 32 return ans; 33 } 34 void solve2(){ 35 num=0; 36 for(int i=0;i<(1<<m);i++){ 37 if(isok(i)){ 38 num++; 39 s[num]=i; 40 ct[num]=counts(i); 41 } 42 } 43 } 44 int main(){ 45 while(~scanf("%d%d",&n,&m)){ 46 memset(mp,0,sizeof(mp)); 47 memset(dp,0,sizeof(dp)); 48 memset(ct,0,sizeof(ct)); 49 memset(s,0,sizeof(s)); 50 memset(state,0,sizeof(state)); 51 for(int i=1;i<=n;i++) 52 for(int j=1;j<=m;j++) 53 cin>>mp[i][j]; 54 solve1(); 55 solve2(); 56 for(int i=1;i<=num;i++){ 57 if(s[i]&state[1])continue; 58 dp[1][i][0]=ct[i]; 59 } 60 for(int i=1;i<=num;i++){ 61 for(int j=1;j<=num;j++){ 62 if(s[i]&s[j])continue; 63 if(state[2]&s[i])continue; 64 if(state[1]&s[j])continue; 65 dp[2][i][j]=max(dp[2][i][j],dp[1][j][0]+ct[i]); 66 } 67 } 68 for(int i=3;i<=n;i++){ 69 for(int j=1;j<=num;j++){ 70 if(s[j]&state[i])continue; 71 for(int k=1;k<=num;k++){ 72 if(s[k]&s[j])continue; 73 if(s[k]&state[i-1])continue; 74 for(int g=1;g<=num;g++){ 75 if(s[k]&s[g])continue; 76 if(s[j]&s[g])continue; 77 if(s[g]&state[i-2])continue; 78 dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][g]+ct[j]); 79 } 80 } 81 } 82 } 83 int ans=0; 84 for(int i=1;i<=num;i++){ 85 for(int j=0;j<=num;j++) 86 ans=max(ans,dp[n][i][j]); 87 } 88 printf("%d\n",ans); 89 } 90 }
标签:style blog http color os io for art
原文地址:http://www.cnblogs.com/chujian123/p/3873758.html