hdu 5691 Sitting in Line

Posted njczy2010

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 5691 Sitting in Line相关的知识,希望对你有一定的参考价值。

传送门

Sitting in Line

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 293    Accepted Submission(s): 143


Problem Description
度度熊是他同时代中最伟大的数学家,一切数字都要听命于他。现在,又到了度度熊和他的数字仆人们玩排排坐游戏的时候了。游戏的规则十分简单,参与游戏的N个整数将会做成一排,他们将通过不断交换自己的位置,最终达到所有相邻两数乘积的和最大的目的,参与游戏的数字有整数也有负数。度度熊为了在他的数字仆人面前展现他的权威,他规定某些数字只能在坐固定的位置上,没有被度度熊限制的数字则可以自由地交换位置。
 

 

Input
第一行一个整数T,表示T组数据。
每组测试数据将以如下格式从标准输入读入:

N

a1p1

a2p2



aNPN

第一行,整数 N(1N16),代表参与游戏的整数的个数。

从第二行到第 (N+1) 行,每行两个整数,ai(10000ai10000)pi(pi=1 或 0pi<N),以空格分割。ai代表参与游戏的数字的值,pi代表度度熊为该数字指定的位置,如果pi=1,代表该数字的位置不被限制。度度熊保证不会为两个数字指定相同的位置。
 

 

Output
第一行输出:"Case #i:"。i代表第i组测试数据。

第二行输出数字重新排列后最大的所有相邻两数乘积的和,即max{a1a2+a2a3+......+aN1aN}
 

 

Sample Input
2 6 -1 0 2 1 -3 2 4 3 -5 4 6 5 5 40 -1 50 -1 30 -1 20 -1 10 -1
 

 

Sample Output
Case #1: -70 Case #2: 4600
 

 

Source
 

 

Recommend
wange2014   |   We have carefully selected several similar problems for you:  5695 5694 5693 5692 5690 
 
 
 
题意:
数组中有些元素位置被固定了,有些可以换位置,求
max{a1a2+a2a3+......+aN1aN}
 
题解:
真不容易,田神给我说了思路,还编了好久2333

状压dp,比赛时没时间思考了。。。

其实,观察所要求的max{a1a2+a2a3+......+aN1aN}

可以发现,你发完前 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 }

 

以上是关于hdu 5691 Sitting in Line的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5691 ——Sitting in Line——————状压动规

hdu 5691 Sitting in Line(状压dp)

HDU5691 Sitting in Line状压DP

hdu 5691 Sitting in Line (状压dp)

hdu 5691 Sitting in Line 状压dp

HDU 5691 Sitting in Line 状压dp