题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5691

题解:

和tsp用的状压差不多,就是固定了一些访问顺序。

dp[i][j]表示前cnt个点中布满状态i且最后一个为j的状态的最大乘积和。

则有dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+a[j]*a[k])。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std; const int maxn = ;
const int INF = 2e9;
int dp[ << ][];
int cnt[ << ];
int a[maxn], p[maxn],f[maxn];
int n; void pre() {
for (int i = ; i < ( << ); i++) {
cnt[i] = ;
for (int j = ; j < ; j++) {
if (i&( << j)) cnt[i]++;
}
}
} void init() {
for (int i = ; i < ( << n); i++) {
for (int j = ; j <= n; j++) {
dp[i][j] = -INF;
}
}
memset(f, -, sizeof(f));
} int main() {
pre();
int tc,kase=;
scanf("%d", &tc);
while (tc--) {
scanf("%d", &n);
init();
for (int i = ; i < n; i++) {
scanf("%d%d", a + i, p + i);
if (p[i] != -) f[p[i]] = i;
}
a[n] = ; p[n] = n;
dp[][n] = ;
for (int i = ; i < ( << n); i++) {
int sum = cnt[i];
for (int j = ; j <= n; j++) {
if ((i&( << j)) == &&j!=n) continue;
//被限制的点:
if (f[sum] != -) {
if ((i&( << f[sum])) == ) {
dp[i | ( << f[sum])][f[sum]] =
max(dp[i | ( << f[sum])][f[sum]], dp[i][j]+a[j]*a[f[sum]]);
}
}
else {
//可以自由移动的点
for (int k = ; k < n; k++) {
if (i&( << k)) continue;
if (p[k] ==-) {
dp[i | ( << k)][k] = max(dp[i | ( << k)][k], dp[i][j] + a[j] * a[k]);
}
}
}
}
}
int ans = -INF;
for (int j = ; j < n; j++) ans = max(ans, dp[( << n) - ][j]);
printf("Case #%d:\n", ++kase);
printf("%d\n", ans);
}
return ;
}

再一发:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=10000000000000000LL;
const double eps=1e-; const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=; LL dp[<<maxn][maxn];
LL arr[maxn];
int pos[maxn],mp[maxn];
int sumv[<<maxn];
int n; void pre(){
clr(sumv,);
for(int i=;i<(<<maxn);i++){
for(int j=;j<maxn;j++){
if(i&(<<j)){
sumv[i]++;
}
}
}
} void init(){
clr(mp,-);
} int main() {
pre();
int tc,kase=;
scf("%d",&tc);
while(tc--){
scf("%d",&n);
init();
rep(i,,n){
scf("%lld%d",&arr[i],&pos[i]);
if(pos[i]>=) mp[pos[i]]=i;
} rep(i,,(<<maxn)) rep(j,,maxn) dp[i][j]=-INFL;
if(mp[]>=){
dp[<<mp[]][mp[]]=;
}else{
for(int i=;i<n;i++){
if(pos[i]>=) continue;
dp[<<i][i]=;
}
} rep(i,,(<<n)){
rep(j,,n){
if(!(i&(<<j))) continue;
if(mp[sumv[i]-]>=&&mp[sumv[i]-]!=j) continue;
rep(k,,n){
if(k==j||!(i&(<<k))) continue;
if(mp[sumv[i^(<<j)]-]>=&&mp[sumv[i^(<<j)]-]!=k) continue;
dp[i][j]=max(dp[i][j],dp[i^(<<j)][k]+arr[k]*arr[j]);
}
}
} LL ans=-INFL;
rep(i,,n) ans=max(ans,dp[(<<n)-][i]);
prf("Case #%d:\n",++kase);
prf("%lld\n",ans); }
return ;
} //end-----------------------------------------------------------------------

hdu 5691 Sitting in Line 状压dp的更多相关文章

  1. hdu 5691 Sitting in line 状压动归

    在本题中,n<=16n<=16n<=16, 不难想到可以将所选数字的编号进行状态压缩. 定义状态 dp[S][j]dp[S][j]dp[S][j],其中 SSS 代表当前所选出的所有 ...

  2. hdu 5691 Sitting in Line

    传送门 Sitting in Line Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/O ...

  3. HDU 6149 Valley Numer II 状压DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6149 题意:中文题目 解法:状压DP,dp[i][j]代表前i个低点,当前高点状态为j的方案数,然后枚 ...

  4. HDU 1074 Doing Homework【状压DP】

    Doing Homework Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he ...

  5. HDU 5434 Peace small elephant 状压dp+矩阵快速幂

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant  Accepts: 38  Submissions: ...

  6. HDU 1074 Doing Homework(状压DP)

    第一次写博客ORZ…… http://acm.split.hdu.edu.cn/showproblem.php?pid=1074 http://acm.hdu.edu.cn/showproblem.p ...

  7. HDU - 4284 Travel(floyd+状压dp)

    Travel PP loves travel. Her dream is to travel around country A which consists of N cities and M roa ...

  8. HDU 4906 Our happy ending (状压DP)

    HDU 4906 Our happy ending pid=4906" style="">题目链接 题意:给定n个数字,每一个数字能够是0-l,要选当中一些数字.然 ...

  9. HDU 1074 Doing Homework (状压dp)

    题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...

随机推荐

  1. dedecms 调用channel子栏目的id问题

    dedecms 说明文档:http://www.dedecms.com/archives/templethelp/help/taghelp.htm {dede:channel type='son' t ...

  2. Oracle数据库中的Function调用参数问题

    在工作中用到了Oracle数据库,需要调用Oracle的Function,Function返回的游标和结果都是通过参数来获取的 比如Function定义如下: , intype, ininttype) ...

  3. Copying Fields to a new Record

    This is a time saving tip for application designer. If you are creating a new record definition and ...

  4. 前端基础 - Defer对象

    参考:http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html < ...

  5. 反编译工具(.NET Reflector )

    1.下载安装原程序,然后运行 Reflector.exe 2.运行注册机,点击 Generate 获得序列号 3.把序列号填写到 Reflector 软件上4.断开网络,点击 Activate 激活( ...

  6. Oracle删除表主键语句

    删除无名主键语句: SELECT * FROM USER_CONS_COLUMNS WHERE TABLE_NAME = '表名'; ALTER TABLE 表名 DROP CONSTRAINT 主键 ...

  7. linux shell 逻辑运算符、逻辑表达式

    shell的逻辑运算符 涉及有以下几种类型,因此只要适当选择,可以解决很多复杂的判断. 一.逻辑运算符  逻辑卷标 表示意思 1. 关于档案与目录的侦测逻辑卷标! -f 常用!侦测『档案』是否存在 e ...

  8. ViewPager中GridView问题

    GridView 嵌套在ViewPager中问题. 1. GridView属性设置无法显示. 正常显示方式 <GridView android:padding="8dip" ...

  9. 在ASP.NET MVC中以post方式传递数组参数的示例

    最近在工作中用到了在ASP.NET MVC中以post方式传递数组参数的情况,记录下来,以供参考. 一.准备参数对象 在本例中,我会传递两个数组参数:一个字符串数组,一个自定义对象数组.这个自定义对象 ...

  10. C# 将汉字转化成拼音

    本文来自http://www.cnblogs.com/yazdao/archive/2011/06/04/2072488.html 首先下载Visual Studio International Pa ...