zoukankan      html  css  js  c++  java
  • 状态压缩 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

  • 相关阅读:
    CSS标题省略号带后缀名称
    vue post下载
    PiNetwork – 国外手机挖矿,目前国外热度很高
    iview table expand 单击当前行控制
    iview 开关变化时控制状态的变更
    CSS伪元素before,after制作左右横线中间文字效果
    idea 修改代码自动编译
    如何获取微信公众号的关注链接?
    震惊,微信小程序可以设置网络字体!真香
    小程序字体大小怎么设置,小程序修改字体样式方法
  • 原文地址:https://www.cnblogs.com/Rlemon/p/2878891.html
Copyright © 2011-2022 走看看