[HDU5691] Sitting in Line

题目

度度熊是他同时代中最伟大的数学家,一切数字都要听命于他。现在,又到了度度熊和他的数字仆人们玩排排坐游戏的时候了。游戏的规则十分简单,参与游戏的N个整数将会做成一排,他们将通过不断交换自己的位置,最终达到所有相邻两数乘积的和最大的目的,参与游戏的数字有整数也有负数。度度熊为了在他的数字仆人面前展现他的权威,他规定某些数字只能在坐固定的位置上,没有被度度熊限制的数字则可以自由地交换位置。(N<=16)

 

题解

dp[mask][i]表示用了mask状态的数字,处理到第i位的最大值,直接状压dp即可

 

代码

#include<cstring>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<fstream>
#include <algorithm>
#include <cmath>
#include<bitset>
#define inf 0x3f3f3f3f

using namespace std;

int a[20],p[20];
int dp[1<<20][20];//状态为i最后一个数为j的最大值 

int main()
{
    int t;
    scanf("%d",&t);
    for(int x=1;x<=t;x++)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&a[i],&p[i]);
        }
        for(int i=0;i<(1<<n);i++)
        {
            for(int j=0;j<n;j++)
            {
                dp[i][j]=-inf;//初始化 
            }
        }
        for(int i=0;i<n;i++)
        {
            if(p[i]==0||p[i]==-1) dp[1<<i][i]=0;//只有固定放在0位的或者随意放的可以放在 0位 
        }
        for(int i=0;i<(1<<n);i++)
        {
            for(int j=0;j<n;j++)if(dp[i][j]!=-inf)
            {
                for(int k=0;k<n;k++)
                {
                    if(((1<<k)&i)==0&&(p[k]==__builtin_popcount(i)||p[k]==-1))//这个数没放过且这个数只能放这或随便放 
                    {
                        dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+a[j]*a[k]);
                    }
                }
            }
        }
        int full=(1<<n)-1;
        int ans=-inf;
        for(int i=0;i<n;i++)
        {
            ans=max(ans,dp[full][i]);
        }
        printf("Case #%d:\n",x);
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2020-12-12 20:14  EDawn  阅读(72)  评论(0)    收藏  举报