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
 
Sample Output
 
Case #1:
-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 ;
}

最新文章

  1. C#组件系列———又一款日志组件:Elmah的学习和分享
  2. cocoapod集成失败,无法找到头文件的解决办法
  3. 配置移动前端开发调试环境(nodejs+npm+weiner的安装和配置使用)
  4. 【练习】显示MySQLadmin 库户籍选项
  5. 9.依赖(Dependence)
  6. Linq to sql 接收存储过程返回的多个结果集
  7. SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-001- DispatcherServlet的高级配置(ServletRegistration.Dynamic、WebApplicationInitializer)
  8. Bamboo简介
  9. Base64编码和解码算法
  10. ##DAY11 UITableView编辑
  11. 服务器编程入门(3)TCP协议详解
  12. Entity FrameWork 实体属性为decimal时默认只保存2位小数
  13. 百度云BCC配置Apache VirtualHost 实现相同域名不同端口访问不同应用
  14. 验证码识别之w3cschool字符图片验证码(easy级别)
  15. 定制json序列化
  16. AngularJs在ng-click函数中获取代表当前元素的DOM对象
  17. 找不到org.restlet.ext.jackson 解决办法
  18. C# Json反序列化
  19. 弹性(flex)布局
  20. Linux进程管理学习资料

热门文章

  1. 转:Java NIO系列教程(四) Scatter/Gather
  2. HDOJ 1083 Courses
  3. PHP常用正则表达式
  4. [Effective JavaScript 笔记]第48条:避免在枚举期间修改对象
  5. unity3d webplayer 16:9 居中显示模板
  6. 使用Unity创造动态的2D水体效果
  7. ZeroMQ(java)之Router/Dealer模式
  8. 最长递增子序列问题 nyoj 17单调递增最长子序列 nyoj 79拦截导弹
  9. javascript quine
  10. BADIP filter