题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3471
题目:有N个原子,两两相撞会释放出能量,并且第 i 个原子跟第 j 个原子相撞后原子j会消失,给出一个矩阵,P[i][j]代表第 i 个原子跟第 j 个原子相撞释放的能量值,求这些原子相撞所能释放的最大能量值。
分析:状态压缩,最多2^10种状态。
集合S表示所有原子集合, i 与 j 相撞, 状态转移方程为:
dp[ S ^ (1 << j) ] = max( dp[ S ^ (1 << j) ], dp[S]+ map[i][j]);
撞击后j不在集合S中 i, j都在集合S中,未撞击前
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 5 const int MAXN = 1 << 11; 6 7 int map[11][11]; 8 int dp[MAXN]; 9 int n; 10 11 int max( int a, int b ) 12 { 13 return a > b ? a : b; 14 } 15 16 int DP() 17 { 18 for ( int S = (1 << n) - 1; S >= 0; S-- ) 19 { 20 for ( int i = 0; i < n; i++ ) 21 if ( S & ( 1 << i ) ) 22 { 23 for ( int j = 0; j < n; j++ ) 24 if ( i != j && S & ( 1 << j ) ) 25 { 26 dp[ S ^ (1 << j) ] = max( dp[ S ^ (1 << j) ], dp[S]+ map[i][j]); 27 } 28 } 29 } 30 31 int MAX = -1; 32 for ( int i = 0; i < (1 << n); i++ ) 33 MAX = max( MAX, dp[i] ); 34 return MAX; 35 } 36 37 int main() 38 { 39 while ( scanf( "%d", &n ), n ) 40 { 41 memset(dp, 0, sizeof(dp) ); 42 for ( int i = 0; i < n; i++ ) 43 for ( int j = 0; j < n; j++ ) 44 scanf( "%d", &map[i][j] ); 45 46 printf( "%d\n", DP() ); 47 } 48 return 0; 49 }