2016"百度之星" - 初赛(Astar Round2A)1002 / HDU 5691 状态压缩DP
2024-10-16 20:21:35
Sitting in Line
Problem Description
度度熊是他同时代中最伟大的数学家,一切数字都要听命于他。现在,又到了度度熊和他的数字仆人们玩排排坐游戏的时候了。游戏的规则十分简单,参与游戏的N个整数将会做成一排,他们将通过不断交换自己的位置,最终达到所有相邻两数乘积的和最大的目的,参与游戏的数字有整数也有负数。度度熊为了在他的数字仆人面前展现他的权威,他规定某些数字只能在坐固定的位置上,没有被度度熊限制的数字则可以自由地交换位置。
Input
第一行一个整数T,表示T组数据。
每组测试数据将以如下格式从标准输入读入:
每组测试数据将以如下格式从标准输入读入:
N
a1p1
a2p2
:
aNPN
第一行,整数 N(1≤N≤16),代表参与游戏的整数的个数。
从第二行到第 (N+1) 行,每行两个整数,ai(−10000≤ai≤10000)、pi(pi=−1 或 0≤pi<N),以空格分割。ai代表参与游戏的数字的值,pi代表度度熊为该数字指定的位置,如果pi=−1,代表该数字的位置不被限制。度度熊保证不会为两个数字指定相同的位置。
Output
第一行输出:"Case #i:"。i代表第i组测试数据。
第二行输出数字重新排列后最大的所有相邻两数乘积的和,即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
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
-70
Case #2:
4600
题解:
我们设定dp[1<<16][16]:dp[i][j]:i为当前选取的状态并以第j个数结尾的最大值,那么答案就是 max{dp[全集][k]} k属于0到n
对于dp[i][j] , i这个状态已经填了x个数,我们准备填第x+1个数时, 如果当前位置必填某个数,那么 就只更新以规定的这个数结尾转移方程
如果没有那就 枚举那么可以任意放的数来更新相应的状态及答案
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include<queue>
#include<vector>
using namespace std;
const int N = <<, M = 1e6+, mod = ,inf = 1e9;
typedef long long ll; ll dp[<<][];
int n,a[N],p[N],H[N],F[N];
int main() {
int T,cas = ;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
memset(H,,sizeof(H));
memset(F,-,sizeof(F));
int tmp = ;
for(int i=;i<n;i++) {
scanf("%d%d",&a[i],&p[i]);
if(p[i]!=-)
H[i] = ,F[p[i]] = i;
}
for(int i=;i<(<<n);i++)
for(int j=;j<n;j++) dp[i][j] = -1e18;
// for(int i=0;i<n;i++)
// for(int j=0;j<n;j++) if(i!=j&&!H[i]&&!H[j]) dp[(1<<i)|(1<<j)][j] = a[i]*a[j], dp[(1<<i)|(1<<j)][i] = a[i]*a[j];
if(F[]!=-) dp[(<<F[])][F[]] = ;
else {
for(int i=;i<n;i++) {
if(!H[i]) dp[(<<i)][i] = ;
}
}
int U = (<<n) - ;
for(int i=;i<=U;i++) {
int counts = ;
for(int j=;j<n;j++) if((<<j)&(i)) counts++;
if(F[counts]!=-) {
counts = F[counts];
for(int j=;j<n;j++) if(i&(<<j)&&counts!=j)dp[i|(<<(counts))][counts] = max(dp[i][j]+a[j]*a[counts],dp[i|(<<counts)][counts]);
}
else {
for(int k=;k<n;k++) {
if((<<k)&(i))
for(int j=;j<n;j++) {
if(!((<<j)&i)) {
dp[i|(<<j)][j] = max(dp[i|(<<j)][j],dp[i][k]+a[k]*a[j]);
}
}
}
}
}
printf("Case #%d:\n",cas++);
ll ans = -1e18;
for(int i=;i<n;i++) ans = max(dp[U][i],ans) ;
printf("%I64d\n",ans);
}
return ;
}
最新文章
- C#组件系列———又一款日志组件:Elmah的学习和分享
- cocoapod集成失败,无法找到头文件的解决办法
- 配置移动前端开发调试环境(nodejs+npm+weiner的安装和配置使用)
- 【练习】显示MySQLadmin 库户籍选项
- 9.依赖(Dependence)
- Linq to sql 接收存储过程返回的多个结果集
- SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-001- DispatcherServlet的高级配置(ServletRegistration.Dynamic、WebApplicationInitializer)
- Bamboo简介
- Base64编码和解码算法
- ##DAY11 UITableView编辑
- 服务器编程入门(3)TCP协议详解
- Entity FrameWork 实体属性为decimal时默认只保存2位小数
- 百度云BCC配置Apache VirtualHost 实现相同域名不同端口访问不同应用
- 验证码识别之w3cschool字符图片验证码(easy级别)
- 定制json序列化
- AngularJs在ng-click函数中获取代表当前元素的DOM对象
- 找不到org.restlet.ext.jackson 解决办法
- C# Json反序列化
- 弹性(flex)布局
- Linux进程管理学习资料
热门文章
- 转:Java NIO系列教程(四) Scatter/Gather
- HDOJ 1083 Courses
- PHP常用正则表达式
- [Effective JavaScript 笔记]第48条:避免在枚举期间修改对象
- unity3d webplayer 16:9 居中显示模板
- 使用Unity创造动态的2D水体效果
- ZeroMQ(java)之Router/Dealer模式
- 最长递增子序列问题 nyoj 17单调递增最长子序列 nyoj 79拦截导弹
- javascript quine
- BADIP filter