HDU4539+状态压缩DP

 1 /*

 2 题意:n行m列的矩阵,1表示可以放东西,0表示不可以。曼哈顿距离为2的两个位置最多只能有一个位置放东西。

 3 问最多放多少个东西。

 4 */

 5 #include<stdio.h>

 6 #include<string.h>

 7 #include<stdlib.h>

 8 #include<algorithm>

 9 #include<iostream>

10 #include<queue>

11 #include<stack>

12 #include<math.h>

13 #include<map>

14 using namespace std;

15 const int maxn = 105;

16 const int maxm = 12;

17 const int N = 170;

18 int mat[ maxn ];

19 int dp[ maxn ][ N ][ N ];

20 int state[ N ];

21 int ones_state[ N ];

22 int Count_ones( int x ){

23     int cnt = 0;

24     while( x ){

25         if( x&1 )

26             cnt++;

27         x>>=1;

28     }

29     return cnt;

30 }    

31 int init( int n,int m ){

32     memset( state,0,sizeof( state ) );

33     memset( ones_state,0,sizeof( state ) );

34     int M = 1<<m;

35     int cnt = 0;

36     for( int i=0;i<M;i++ ){

37         if( (i&(i<<2))==0&&(i&(i>>2))==0 ){

38             state[ cnt ] = i;

39             ones_state[ cnt ] = Count_ones( i );

40             cnt++;

41         }

42     }

43     //printf("cnt=%d\n",cnt);最多169种状态!!

44     return cnt;

45 }

46 void DP( int cnt,int n,int m ){

47     memset( dp,-1,sizeof( dp ) );

48         for( int i=0;i<cnt;i++ ){

49             if( (state[i]&mat[0])==0 )

50                 dp[0][i][0] = ones_state[ i ];

51         }//初始化

52     for( int i=1;i<n;i++ ){

53         for( int j=0;j<cnt;j++ ){

54             if( (state[j]&mat[i])==0 ){

55                 for( int k=0;k<cnt;k++ ){

56                     if( (state[j]&(state[k]<<1))==0&&(state[j]&(state[k]>>1))==0 ){

57                         for( int k2=0;k2<cnt;k2++ ){

58                             if( dp[i-1][k][k2]==-1 ) continue;

59                             if( (state[j]&state[k2])==0&&(state[k]&(state[k2]>>1))==0&&(state[k]&(state[k2]<<1))==0 )

60                                 dp[ i ][ j ][ k ] = max( dp[i][j][k],dp[i-1][k][k2]+ones_state[j] );

61                         }

62                     }

63                 }

64             }

65         }

66     }

67 }

68 int main(){

69     int n,m;

70     while( scanf("%d%d",&n,&m)==2 ){

71         int cnt = init( n,m );

72         memset( mat,0,sizeof( mat ) );

73         int tmp;

74         for( int i=0;i<n;i++ ){

75             for( int j=0;j<m;j++ ){

76                 scanf("%d",&tmp);

77                 if( tmp==0 ){

78                     mat[ i ] |= (1<<j);

79                 }

80             }

81         }

82         DP( cnt,n,m );

83         int ans = 0;

84         for( int i=0;i<cnt;i++ )

85             for( int j=0;j<cnt;j++ )

86                 ans = max( ans,dp[n-1][i][j]);

87         printf("%d\n",ans);

88     }

89     return 0;

90 }
View Code

 

你可能感兴趣的:(HDU)