HLG1473教主的遗产【状压dp】
教主的遗产 | ||||||
|
||||||
Description | ||||||
恭送教主! 教主在2012年7月19日上午10:48,坐上前往北京的火车,从此开始了高富帅的生活。 在教主的的大学四年ACM生涯中,他用事实告诉我们,要想在比赛拿奖,除了平时的刻苦努力外,很大一部分还要依赖比赛时是
做题策略,简单来讲就是做题顺序,唯有想把能过的都过掉,然后再过难题,这样才能在比赛中拿奖。
我们将用这个做题顺序量化表示,即AC系数,AC系数越大,拿奖可能性就越大。
在比赛中会给出n个题,不同做题顺序会有不同的AC系数,假如A先做,B后做的话,B对A的AC系数为4, 反过来 B先做,A后做的话,A对B的AC系数为5,说明先做B后做A将得到更高的AC系数。
设Sij表示第i题在第j题做完后才做获得的AC系数,有三道题a, b, c,做题顺序为bac,则系数和为:Sum = Sab + Scb + Sca。 求一个做题顺序,使得AC系数和最大。
|
||||||
Input | ||||||
有多组测试数据。
对于每组测试数据,第一行为n(1<=n<=16),表示题目数量。
接下来有n行,每行n个数字,对于1+i行的第j个数字Sij(0 <= Sij <= 32), 表示第i题在第j题之后做的AC系数。
|
||||||
Output | ||||||
每组测试数据输出一行,包含一个数,为最大系数和。 | ||||||
Sample Input | ||||||
1 0 2 0 2 4 0 3 0 2 4 4 0 25 17 15 0 |
||||||
Sample Output | ||||||
0 4 46 |
||||||
Source | ||||||
2012 Summer Contest 1 - DP | ||||||
Author | ||||||
黄李龙@HRBUST |
分析:状态压缩 dp[i]表示到达状态i的最大值 由于每一次加入一个新题 都会与前面的旧题产生一个系数 所以扫描一遍就行了
这个题跟那个一笔画的思路很像 由于|的性质每次加入一个点状态都会往后转移 所以状态转移是成立的
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 7 const int maxn = 17; 8 int a[maxn][maxn]; 9 int n; 10 int dp[1 << maxn]; 11 12 int DP() { 13 int Max = 1 << n; 14 memset(dp, -1, sizeof(dp)); 15 dp[0] = 0; 16 for(int i = 0; i < Max; i++) { 17 if(dp[i] == -1) continue; 18 // printf("i == %d\n", i); 19 for(int j = 1; j <= n; j++) { 20 if(( i & ( 1 << ( j - 1 ) ) ) == 0) { 21 // printf("j == %d\n", j); 22 int sum = 0; 23 for(int k = 1; k <= n; k++) { 24 if(k == j) continue; 25 if((i & ( 1 << ( k - 1) ) ) ) { 26 // printf("k ==== %d\n", k); 27 sum += a[j][k]; 28 } 29 } 30 // printf("sum == %d\n", sum); 31 dp[i | ( 1 << ( j - 1 ) ) ] = max(dp[i | ( 1 << ( j - 1 ) )], dp[i] + sum); 32 } 33 } 34 } 35 return dp[Max - 1]; 36 } 37 int main() { 38 while(EOF != scanf("%d",&n) ) { 39 for(int i = 1; i <= n; i++) { 40 for(int j = 1; j <= n; j++) { 41 scanf("%d",&a[i][j]); 42 } 43 } 44 //` for(int i = 1; i <= n; i++) { 45 //` for(int j = 1; j <= n; j++) { 46 //` printf("%d ", a[i][j]); 47 //` } puts(""); 48 //` } 49 printf("%d\n", DP()); 50 } 51 return 0; 52 }