HDU2167+状态压缩DP
状态压缩dp
详见代码
1 /* 2 状态压缩dp 3 dp[ i ][ j ]:第i行j状态的最大和 4 dp[i][j] = max( dp[i-1][k]+sum[i][j] ); 5 题意:给定一个N*N的方格,让你在里面取出一些数使其和最大,要求每一个数不能与其相邻的8个数同时取出 6 */ 7 #include<stdio.h> 8 #include<string.h> 9 #include<stdlib.h> 10 #include<algorithm> 11 #include<iostream> 12 #include<queue> 13 #include<stack> 14 #include<math.h> 15 #include<map> 16 using namespace std; 17 const int maxn = 15; 18 int sum[ maxn+5 ][ 1<<maxn ];//sum[i][j]:第i行j状态的数字和 19 int s[ 1<<maxn ];//合格的状态的集合 20 int dp[ maxn+5 ][ 1<<maxn ];//dp[i][j]:第i行j状态的最大和 21 int mat[ maxn+5 ][ maxn+5 ]; 22 int binary[ maxn+5 ]; 23 void init_binary( ){ 24 binary[ 0 ] = 1; 25 for( int i=1;i<20;i++ ){ 26 binary[ i ] = 2*binary[ i-1 ]; 27 } 28 } 29 30 int solve( int n ){ 31 int cnt_state = 0; 32 memset( dp,0,sizeof( dp ) ); 33 memset( sum,0,sizeof( sum ) ); 34 int N = (1<<n); 35 for( int i=0;i<N;i++ ){ 36 if( ((i<<1)&i)==0 ){ 37 s[ cnt_state++ ] = i; 38 } 39 }//选出无相邻数字的状态 40 for( int i=0;i<n;i++ ){ 41 for( int j=0;j<cnt_state;j++ ){ 42 for( int k=0;k<n;k++ ){ 43 if( binary[k]&s[ j ] ){ 44 sum[ i ][ j ] += mat[ i ][ k ]; 45 } 46 } 47 } 48 }//预处理出sum值 49 int ans = 0; 50 for( int i=0;i<cnt_state;i++ ){ 51 dp[0][ i ] = sum[ 0 ][ i ]; 52 ans = max( ans,dp[0][i] ); 53 } 54 for( int i=1;i<n;i++ ){ 55 for( int j=0;j<cnt_state;j++ ){ 56 for( int k=0;k<cnt_state;k++ ){//前一行的状态 57 if( (s[j]&s[k])==0 ){ 58 if( (s[j]&(s[k]<<1))==0 ){ 59 if( (s[j]&(s[k]>>1))==0 ){ 60 dp[ i ][ j ] = max( dp[ i-1 ][ k ]+sum[ i ][ j ],dp[ i ][ j ] ); 61 } 62 } 63 } 64 } 65 ans = max( ans,dp[i][j] ); 66 } 67 } 68 return ans; 69 } 70 71 int main(){ 72 char str[ 105 ]; 73 init_binary(); 74 while( gets( str ) ){ 75 int len = strlen( str ); 76 int n = 0; 77 for( int i=0;i<len;i+=3 ){ 78 mat[0][n++] = (str[i]-'0')*10+str[i+1]-'0'; 79 } 80 for( int i=1;i<n;i++ ){ 81 gets(str); 82 int cc = 0; 83 for( int j=0;j<len;j+=3 ){ 84 mat[i][cc++] = (str[j]-'0')*10+str[j+1]-'0'; 85 } 86 } 87 int ans = solve( n ); 88 printf("%d\n",ans); 89 getchar(); 90 } 91 return 0; 92 }
keep moving...