状压Dp_______Sitting in Line( hdu 5691 2016百度之星初赛A )
2016-06-10 16:20
381 查看
Problem Description
度度熊是他同时代中最伟大的数学家,一切数字都要听命于他。现在,又到了度度熊和他的数字仆人们玩排排坐游戏的时候了。游戏的规则十分简单,参与游戏的N个整数将会做成一排,他们将通过不断交换自己的位置,最终达到所有相邻两数乘积的和最大的目的,参与游戏的数字有整数也有负数。度度熊为了在他的数字仆人面前展现他的权威,他规定某些数字只能在坐固定的位置上,没有被度度熊限制的数字则可以自由地交换位置。
Input
第一行一个整数TT,表示TT组数据。
每组测试数据将以如下格式从标准输入读入:
NN
a_1
p_1a1p1
a_2
p_2a2p2
:
a_N
P_NaNPN
第一行,整数 N
(1 \leq N \leq 16)N(1≤N≤16),代表参与游戏的整数的个数。
从第二行到第 (N
+ 1)(N+1) 行,每行两个整数,a_{i}
(-10000 \leq a_{i} \leq 10000)ai(−10000≤ai≤10000)、p_{i}
(p_{i} = -1pi(pi=−1 或 0
\leq p_{i} < N)0≤pi<N),以空格分割。a_{i}ai代表参与游戏的数字的值,p_{i}pi代表度度熊为该数字指定的位置,如果p_{i}
= -1pi=−1,代表该数字的位置不被限制。度度熊保证不会为两个数字指定相同的位置。
Output
第一行输出:"Case #i:"。ii代表第ii组测试数据。
第二行输出数字重新排列后最大的所有相邻两数乘积的和,即max{a_1\cdot
a_2+a_2\cdot a_3+......+a_{N-1}\cdot a_N}max{a1⋅a2+a2⋅a3+......+aN−1⋅aN}。
Sample Input
Sample Output
分析:
数字放在a[i]中,标记放在b[i]中
原本以为是简单的贪心,结果发现局部最优并不能推出整体最优。后来仔细一看发现是一个状压dp。
dp[i][j] 表示状态为i以a[i]元素结尾,状态为j的最大和。( 状态的意思是当前已经选择了哪些数。 )
那么答案就是 dp[i][(1<<n)-1] { 0<=i<n } 中的最大值
代码:
度度熊是他同时代中最伟大的数学家,一切数字都要听命于他。现在,又到了度度熊和他的数字仆人们玩排排坐游戏的时候了。游戏的规则十分简单,参与游戏的N个整数将会做成一排,他们将通过不断交换自己的位置,最终达到所有相邻两数乘积的和最大的目的,参与游戏的数字有整数也有负数。度度熊为了在他的数字仆人面前展现他的权威,他规定某些数字只能在坐固定的位置上,没有被度度熊限制的数字则可以自由地交换位置。
Input
第一行一个整数TT,表示TT组数据。
每组测试数据将以如下格式从标准输入读入:
NN
a_1
p_1a1p1
a_2
p_2a2p2
:
a_N
P_NaNPN
第一行,整数 N
(1 \leq N \leq 16)N(1≤N≤16),代表参与游戏的整数的个数。
从第二行到第 (N
+ 1)(N+1) 行,每行两个整数,a_{i}
(-10000 \leq a_{i} \leq 10000)ai(−10000≤ai≤10000)、p_{i}
(p_{i} = -1pi(pi=−1 或 0
\leq p_{i} < N)0≤pi<N),以空格分割。a_{i}ai代表参与游戏的数字的值,p_{i}pi代表度度熊为该数字指定的位置,如果p_{i}
= -1pi=−1,代表该数字的位置不被限制。度度熊保证不会为两个数字指定相同的位置。
Output
第一行输出:"Case #i:"。ii代表第ii组测试数据。
第二行输出数字重新排列后最大的所有相邻两数乘积的和,即max{a_1\cdot
a_2+a_2\cdot a_3+......+a_{N-1}\cdot a_N}max{a1⋅a2+a2⋅a3+......+aN−1⋅aN}。
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
分析:
数字放在a[i]中,标记放在b[i]中
原本以为是简单的贪心,结果发现局部最优并不能推出整体最优。后来仔细一看发现是一个状压dp。
dp[i][j] 表示状态为i以a[i]元素结尾,状态为j的最大和。( 状态的意思是当前已经选择了哪些数。 )
那么答案就是 dp[i][(1<<n)-1] { 0<=i<n } 中的最大值
代码:
#include <stdio.h> #include <string.h> #define INF 1700000000 int dp[17][(1<<16)-1];//dp[j][k] 表示第j个数结尾状态为k的最大值 int a[17]; int b[17]; int n; int num(int x) { int ans=0; while(x) { if(x%2==1) ans++; x>>=1; } return ans; } int MAX(int a,int b) { return a>b?a:b; } int main() { int t,i,j,k,Case = 0; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i = 0 ; i < n ; i ++) scanf("%d%d",&a[i],&b[i]); for(j = 0 ; j < n ; j ++) for(k = 0 ; k < (1<<n) ; k ++) dp[j][k] = -INF; for(i = 0 ; i < n ; i ++) { if(b[i] == -1 || b[i] == 0) { dp[i][(1<<i)] = 0; } } for(i = 0 ; i <(1<<n) ; i ++) { for(j = 0 ; j < n ; j ++) { if(dp[j][i] != -INF) { for(k = 0 ; k < n ; k ++) { if((i&(1<<k)) == 0 &&(b[k] == -1 || b[k] == num(i))) { dp[k][i|(1<<k)] = MAX(dp[k][i|(1<<k)],dp[j][i] + a[j]*a[k]); } } } } } int ans = -INF; for(i= 0 ; i < n ; i ++) ans = MAX(ans,dp[i][(1<<n)-1]); printf("Case #%d:\n%d\n",++Case,ans); } return 0; }
相关文章推荐
- POJ 3254 - Corn Fields [状压DP]
- poj 2836
- poj 3254
- POJ 2441
- 2014 西安邀请赛状压DP
- Mega Man’s Missions
- HDU 5713 K个联通块 状压dp枚举子集 (2016百度之星复赛)
- 【2015新手赛网络赛】 1004 Good Subsets
- HDU 5561 【2015合肥现场赛】 Kingdom of Tree
- 关于AC自动机与DP的总结
- nyoj 合并游戏(状态压缩dp)
- HDU 5135 Little Zu Chongzhi's Triangles (2014年广州赛区现场赛I题)
- 【PA2014】【BZOJ3717】Pakowanie
- 【SCOI2007】【BZOJ1072】排列perm
- 【CERC2012】【BZOJ4057】Kingdoms
- 【SDOI2009】【BZOJ1879】Bill的挑战
- 【BZOJ2064】分裂
- 【清华集训2014】【BZOJ3812】主旋律
- Codevs2880 送外卖
- codeforces #302 Remembering Strings (dp)