状态压缩 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

你可能感兴趣的:(压缩)