状态压缩 DP | 搜索

hdu 2280(DP)
View Code
 1 #include<cstdlib>
 2 #include<cstdio>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<cstring>
 7 using namespace std;
 8 const int m=5;
 9 const int oo=5100;
10 int dp[1010][40];
11 int n,c;
12 int mz[1010];
13 void dfs(int p,int up,int down,int c,int r){
14     if (p>=m){
15         if (c<dp[r][down]) dp[r][down]=c;
16         return;
17     }
18     //2
19     if (p<4 && ((up&(1<<p))==0) && ((down&(3<<p))==0))
20     dfs(p+1,up|(1<<p),down|(3<<p),c,r);
21     //3
22     if (p<4 && ((up&(3<<p))==0) && ((down&(3<<p))==0))
23     dfs(p+2,up|(3<<p),down|(3<<p),c,r);
24     //4
25     if (p<4 && ((up&(3<<p))==0))
26     dfs(p+2,up|(3<<p),down,c,r);
27     //5
28     if ( ((up&(1<<p))==0) && ((down&(1<<p))==0))
29     dfs(p+1,up|(1<<p),down|(1<<p),c,r);
30     //6
31     if (p>0 && ((up&(1<<p))==0) && ((down&(3<<p-1))==0))
32     dfs(p+1,up|(1<<p),down|(3<<(p-1)),c,r);
33     //7
34     if (p<4 && ((up&(3<<p))==0) && ((down&(1<<p))==0))
35     dfs(p+2,up|(3<<p),down|(1<<p),c,r);
36     //8
37     if (p<4 && ((up&(3<<p))==0) && ((down&(1<<p+1))==0))
38     dfs(p+2,up|(3<<p),down|(1<<p+1),c,r);
39     
40     if (up&(1<<p)) dfs(p+1,up,down,c,r);
41     else dfs(p+1,up|(1<<p),down,c+1,r);
42 }
43 int cal(int x){
44     int ret=0;
45     for (int i=0;i<m;i++){
46         if ((x&(1<<i))==0) ret++;
47     }
48     return ret;
49 }
50 int main(){
51     while (~scanf("%d%d",&n,&c)){
52     //    cout<<n<<" "<<c<<endl;
53         memset(mz,0,sizeof(mz));
54         for (int i=1;i<=n;i++){
55             char s[6];
56             scanf("%s",s);
57         //    cout<<s<<endl;
58             for (int j=0;j<m;j++){
59                 if (s[j]=='1') mz[i]|=1<<(m-j-1);
60             }
61         //    cout<<mz[i]<<endl;
62         }
63         mz[n+1]=(1<<m)-1;
64         for (int i=0;i<=n+1;i++){
65             for (int j=0;j<(1<<m);j++) dp[i][j]=oo;
66         }
67         dp[1][mz[1]]=0;
68         for (int i=1;i<=n;i++){
69             for (int j=0;j<(1<<m);j++)if (dp[i][j]<=c){
70                 dfs(0,j,mz[i+1],dp[i][j],i+1);
71             }
72         }    
73     /*    for (int i=1;i<=n+1;i++){
74             for (int j=0;j<(1<<m);j++)
75             if (dp[i][j]!=oo)cout<<j<<" "<<dp[i][j]<<endl;
76             cout<<endl;
77         }
78     */    int flag=0;
79     //    cout<<dp[n+1][(1<<m)-1]<<endl;
80     //    for (int i=0;i<(1<<m) && flag==0;i++){
81             if (dp[n+1][(1<<m)-1]<=c) flag=1;
82     //    }    
83         if (flag) printf("YES\n");
84         else printf("NO\n");
85     }
86     return 0;
87 }

2

hdu 2442 (DP 同hdu 2280)
View Code
 1 //14:11
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<cstdio>
 7 using namespace std;
 8 int n,m;
 9 int dp[102][1<<6][1<<6];
10 //dp[i][j][k]表示第i-1层状态为j,第i层状态为k时,
11 //前i层能填的最多的格子数; j=(00101)2  ,1表示被填,0表示空; 
12 void dfs(int p,int u,int v,int c,int x,int s){
13     //p表示枚举第s-2行的状态,u是s-2行的状态,v是s-1行的状态;
14     //c是dp[s-1][u][v]时最多能填的格子个数,s是当前求的行; 
15     if (p>=m){
16         if (c>dp[s][v][x]) dp[s][v][x]=c;
17         return ;
18     }
19 
20     //1
21     if (p>0 && (u&(1<<p))==0 && (v&(3<<p-1))==0 && (x&(1<<p))==0)
22     dfs(p+1,u|(1<<p),v|(3<<p-1),c+4,x|(1<<p),s);
23     //2
24     if (p<m-1 && p>0 && (u&(1<<p))==0 && (v&(7<<p-1))==0 && (x&(1<<p))==0)
25     dfs(p+1,u|(1<<p),v|(7<<p-1),c+5,x|(1<<p),s);
26     //3
27     if (p<m-2 && (u&(7<<p))==0 && (v&(2<<p))==0)
28     dfs(p+3,u|(7<<p),v|(2<<p),c+4,x,s);
29     //4
30     if (p<m-2 && (u&(7<<p))==0 && (v&(4<<p))==0)
31     dfs(p+3,u|(7<<p),v|(4<<p),c+4,x,s);
32     //5
33     if (p<m-1 && (u&(3<<p))==0 && (v&(2<<p))==0 && (x&(2<<p))==0)
34     dfs(p+2,u|(3<<p),v|(2<<p),c+4,x|(2<<p),s);
35     
36     if (u&(1<<p)) dfs(p+1,u,v,c,x,s);//该格子已经被填了。 
37     else dfs(p+1,u,v,c,x,s);//让该格子为空; 
38     
39     
40     
41 }
42 int main(){
43     while (~scanf("%d%d",&n,&m)){
44         memset(dp,-1,sizeof(dp));
45         dp[1][0][0]=0;
46         for (int i=2;i<=n;i++){
47             for (int j=0;j<(1<<m);j++){
48                 for (int k=0;k<(1<<m);k++) if (dp[i-1][j][k]>=0)
49                 //由dp[i-1][j][k]递推dp[i][][] 
50                 dfs(0,j,k,dp[i-1][j][k],0,i);//枚举5中方块能放的可能; 
51             }
52         }
53         int ans=0;
54         for (int i=0;i<(1<<m);i++) {
55         //    if (dp[n][i][0]==5) cout<<"**"<<i<<endl;
56             ans=max(ans,dp[n][i][0]);
57         //dp[n][][0],表示在原图的基础上再多加一层,并且为0时最多能填的个数; 
58         }
59         printf("%d\n",ans);
60     }
61     return 0;
62 }

2

hdu 2640 (DP hdu2442简化版)
方法一:同hdu2442,递推时直接枚举;
View Code
 1 //15:36
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<cstdio>
 7 #include<cstring>
 8 using namespace std;
 9 
10 int dp[102][1<<8][1<<8]; 
11 int mz[102];
12 int n,m;
13 void dfs(int p,int u,int v,int x,int c,int s){
14     if (p>=m) {
15         if (c>dp[s][v][x]) dp[s][v][x]=c;
16         return ; 
17     } 
18     if (p>0 && p<m-1 && (u&(1<<p))==0 && (v&(7<<p-1))==0 && (x&(1<<p))==0)
19     dfs(p+1,u|(1<<p),v|(7<<p-1),x|(1<<p),c+1,s);
20     dfs(p+1,u,v,x,c,s);
21      
22 } 
23 int main(){
24     int T;
25     scanf("%d",&T);
26     while (T--){
27         scanf("%d%d",&n,&m);
28         for (int i=0;i<n;i++){
29             char s[10];
30             scanf("%s",s);
31             mz[i]=0; 
32             for (int j=0;j<m;j++){
33                 if (s[j]=='#') mz[i]|=1<<m-j-1; 
34             } 
35         } 
36         mz[n]=(1<<m)-1; 
37         memset(dp,-1,sizeof(dp)); 
38         dp[1][mz[0]][mz[1]]=0;
39         for (int i=2;i<=n;i++){
40             for (int j=0;j<(1<<m);j++){
41                 for (int k=0;k<(1<<m);k++) if (dp[i-1][j][k]>=0){
42                     dfs(0,j,k,mz[i],dp[i-1][j][k],i); 
43                 } 
44             } 
45         } 
46         int ans=0;
47         for (int i=0;i<(1<<m);i++){
48             if (dp[n][i][(1<<m)-1]>ans) ans=dp[n][i][(1<<m)-1]; 
49         } 
50         printf("%d\n",ans); 
51     } 
52     return 0; 
53 } 

2

方法二:因为只有一种brick,所以以中心代表一个brick,
转化成当在(i,j)放了一个brick后,(i-1,j),(i+1,j),(i,j-1),(i,j+1)位置为禁区;
然后就可以递推了,程序是暑假写的,比较繁琐;
View Code
 1 //22:54
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cstdlib>
 6 #include<iostream>
 7 using namespace std;
 8 const int N=110;
 9 int a[N];
10 int num[N];
11 int mp[N]; 
12 int dp[N][60][60]; 
13 int n,m,sz; 
14 void init()
15 {
16     sz=0; 
17     for (int i=0;i<(1<<m);i++){
18        if ((i&(i>>1))||(i&(i<<1))) continue;
19        if ((i&(i>>2))||(i&(i<<2))) continue;
20        if ((i&1) || (i&(1<<(m-1)))) continue;
21        a[sz++]=i;
22 //      cout<<i<<" ";  
23     } 
24    // cout<<endl; 
25   //  cout<<sz<<endl; 
26     for (int i=0;i<sz;i++){
27        num[i]=0; 
28        for (int j=0;j<m;j++) 
29        if (a[i]&(1<<j)) num[i]++; 
30      //  cout<<num[i]<<" "; 
31     } 
32    // cout<<endl; 
33 } 
34 int main()
35 {
36    int maxn;
37   // freopen("D:\in.txt","r",stdin); 
38    scanf("%d",&maxn);
39    while (maxn--)
40    {
41        scanf("%d%d\n",&n,&m);    
42        for (int i=0;i<n;i++){
43          char s[10];
44          gets(s);
45          mp[i]=0; 
46          for (int j=m-1;j>=0;j--){
47             if (s[j]=='#')
48             mp[i]|=1<<(m-j-1);   
49          } 
50       } 
51       if (n<3){
52         printf("0\n");
53         continue; 
54       } 
55       init();
56       memset(dp,0,sizeof(dp)); 
57       for (int i=0;i<sz;i++){
58            if((mp[1]&a[i])||(mp[0]&a[i])||(mp[2]&a[i])) continue;
59            if ((mp[1]&(a[i]>>1))||(mp[1]&(a[i]<<1))) continue;   
60            dp[1][i][0]=num[i]; 
61       } 
62    
63       for (int c=2;c<n-1;c++){
64          for (int i=0;i<sz;i++){
65           if ((mp[c]&a[i])||(mp[c-1]&a[i])||(mp[c+1]&a[i]))continue;
66           if ((mp[c]&(a[i]>>1))||(mp[c]&(a[i]<<1)))continue;         
67           for (int j=0;j<sz;j++){
68                if ((mp[c-1]&a[j])||(mp[c-2]&a[j])||(mp[c]&a[j]))continue;
69                if ((mp[c-1]&(a[j]>>1))||(mp[c-1]&(a[j]<<1)))continue;         
70                  for (int k=0;k<sz;k++){
71                    if ((mp[c-2]&a[k])||(mp[c-1]&a[k]))continue;
72                    if ((mp[c-2]&(a[k]>>1))||(mp[c-2]&(a[k]<<1)))continue;             
73                    if ((a[i]&a[j])||(a[j]&a[k])||(a[i]&a[k])) continue;
74                    if ((a[i]&(a[j]>>1))||(a[i]&(a[j]<<1)))continue;
75                    if ((a[j]&(a[k]>>1))||(a[j]&(a[k]<<1))) continue; 
76                    dp[c][i][j]=max(dp[c-1][j][k]+num[i],dp[c][i][j]);    
77             } 
78           } 
79         }   
80       }  
81       int maxv=0;
82       for (int i=0;i<sz;i++)
83       {
84           for (int j=0;j<sz;j++)
85          {
86            if (dp[n-2][i][j]>maxv) maxv=dp[n-2][i][j]; 
87          } 
88       } 
89       printf("%d\n",maxv);    
90    } 
91    return 0; 
92 } 

2

2

原文地址:https://www.cnblogs.com/Rlemon/p/2878891.html