标签:
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 293 Accepted Submission(s): 143
状压dp,比赛时没时间思考了。。。
其实,观察所要求的max{a1⋅a2+a2⋅a3+......+aN−1⋅aN}
可以发现,你发完前 i - 1 位 元素后,准备放第 i 位 元素时,当前的 max 只 与 a[i-1] 有关了 (a[i - 1] * a[i]),所以可以用状压dp
定义 dp[o][i] 为放完第i位(以a[i] 为结尾),状态 o 时的max
遍历的顺序见代码
17232841 | 2016-05-21 22:22:30 | Accepted | 5691 | 1294MS | 11724K | 2946B | G++ | czy |
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 #include <vector> 7 8 using namespace std; 9 10 #define N 19 11 #define ll long long 12 13 ll ma; 14 ll a[N]; 15 int p[N]; 16 int have[N]; 17 int n; 18 ll dp[ (1 << 17) ][N]; 19 int tot; 20 ll inf; 21 vector<int> G[N]; 22 23 int cal(int x) 24 { 25 int ret = 0; 26 while(x){ 27 ret += (x & 1); 28 x /= 2; 29 } 30 return ret; 31 } 32 33 void ini() 34 { 35 int o; 36 for(o = 0;o < n;o++){ 37 G[o].clear(); 38 } 39 for(o = 0;o < tot;o++){ 40 G[ cal(o) ].push_back(o); 41 } 42 } 43 44 int main() 45 { 46 47 int T; 48 //freopen("in.txt","r",stdin); 49 //freopen("out.txt","w",stdout); 50 scanf("%d",&T); 51 for(int ccnt = 1;ccnt <= T;ccnt++){ 52 scanf("%d",&n); 53 inf = (1LL << 60); 54 ma = -inf; 55 tot = (1 << n); 56 ini(); 57 int i; 58 memset(have,-1,sizeof(have)); 59 for(i = 0;i < n;i++){ 60 scanf("%I64d%d",&a[i],&p[i]); 61 if(p[i] != -1){ 62 have[ p[i] ] = i; 63 } 64 } 65 int o,nt; 66 for(o = 0;o < tot;o++){ 67 for(i = 0;i < n;i++){ 68 dp[o][i] = -inf; 69 } 70 } 71 for(i = 0;i < n;i++){ 72 if(p[i] == 0 || p[i] == -1){ //放在第一个 73 dp[ (1 << i) ][i] = 0; 74 } 75 } 76 77 /* 78 for(i = 0;i < n;i++){ 79 for(int j = 0;j < G[i].size();j++){ 80 printf(" i =%d j = %d g= %d\n",i,j,G[i][j]); 81 } 82 }*/ 83 for(i = 1;i < n;i++){ //放第i位 84 int sz = G[i].size(); 85 for(int j = 0;j < sz;j++){ //遍历含有i个1的所有数 86 o = G[i][j]; 87 for(int k = 0;k < n;k++) //把第k个数放在第i位 88 { 89 90 if( o & (1 << k) ) continue; //k已经放了 91 if( p[k] != -1 && p[k] != i ) continue; //k被固定了 92 if( have[i] != -1 && have[i] != k ) continue; //位置i被固定了 93 nt = o | (1 << k); 94 //printf(" i = %d o = %d k = %d nt = %d\n",i,o,k,nt); 95 for(int pr = 0;pr < n;pr++){ 96 if( (o & (1 << pr ) ) == 0) continue; //pr不在o里 97 if( dp[o][pr] == -inf ) continue; 98 //printf(" i = %d o = %d k = %d nt = %d pr = %d\n",i,o,k,nt,pr); 99 dp[nt][k] = max(dp[nt][k],dp[o][pr] + a[pr] * a[k]); 100 } 101 } 102 } 103 } 104 /* 105 for(o = 0;o < tot;o++){ 106 for(i = 0;i < n;i++){ 107 printf(" o = %d i = %d dp = %I64d\n",o,i,dp[o][i]); 108 } 109 }*/ 110 for(i = 0;i < n;i++){ 111 ma = max(ma,dp[tot - 1][i]); 112 } 113 printf("Case #%d:\n",ccnt); 114 printf("%I64d\n",ma); 115 } 116 117 return 0; 118 }
标签:
原文地址:http://www.cnblogs.com/njczy2010/p/5515788.html