2016"百度之星" - 初赛(Astar Round2A)1002 / HDU 5691 状态压缩DP

Posted Meek

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2016"百度之星" - 初赛(Astar Round2A)1002 / HDU 5691 状态压缩DP相关的知识,希望对你有一定的参考价值。

Sitting in Line

 

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
 

 

题解:

  我们设定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 = 1<<17, M = 1e6+10, mod = 1000000007,inf = 1e9;
typedef long long ll;

ll dp[1<<17][17];
int n,a[N],p[N],H[N],F[N];
int main() {
    int T,cas = 1;
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        memset(H,0,sizeof(H));
        memset(F,-1,sizeof(F));
        int tmp = 0;
        for(int i=0;i<n;i++) {
            scanf("%d%d",&a[i],&p[i]);
            if(p[i]!=-1)
             H[i] = 1,F[p[i]] = i;
        }
        for(int i=0;i<(1<<n);i++)
            for(int j=0;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[0]!=-1) dp[(1<<F[0])][F[0]] = 0;
       else {
        for(int i=0;i<n;i++) {
            if(!H[i]) dp[(1<<i)][i] = 0;
        }
       }
       int U = (1<<n) - 1;
        for(int i=1;i<=U;i++) {
            int counts = 0;
            for(int j=0;j<n;j++) if((1<<j)&(i)) counts++;
            if(F[counts]!=-1) {
                counts = F[counts];
                for(int j=0;j<n;j++) if(i&(1<<j)&&counts!=j)dp[i|(1<<(counts))][counts] = max(dp[i][j]+a[j]*a[counts],dp[i|(1<<counts)][counts]);
            }
            else {
                for(int k=0;k<n;k++) {
                    if((1<<k)&(i))
                    for(int j=0;j<n;j++) {
                       if(!((1<<j)&i)) {
                            dp[i|(1<<j)][j] = max(dp[i|(1<<j)][j],dp[i][k]+a[k]*a[j]);
                        }
                    }
                }
            }
        }
        printf("Case #%d:\n",cas++);
        ll ans = -1e18;
        for(int i=0;i<n;i++) ans = max(dp[U][i],ans) ;
        printf("%I64d\n",ans);
    }
    return 0;
}

 

以上是关于2016"百度之星" - 初赛(Astar Round2A)1002 / HDU 5691 状态压缩DP的主要内容,如果未能解决你的问题,请参考以下文章

2016"百度之星" - 初赛(Astar Round2B)

2016"百度之星" - 初赛(Astar Round2A)

2016"百度之星" - 初赛(Astar Round2B)

2016"百度之星" - 初赛(Astar Round2A)

2016"百度之星" - 初赛(Astar Round2B)

2016"百度之星" - 初赛(Astar Round2A)All X(数学 矩阵)