2016"百度之星" - 初赛(Astar Round2A)1002(dp状压)

题目链接:点这里!!!!!


题意:中文题。


题解:

参考别人的。。。。

设dp[i][j]为i这个状态下以a[j]结尾的情况下的最大值。

dp[i][j]可以转变成dp[i|(1<<k)][k],我们只要注意第k数有没有被固定就可以。

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

时间复杂度为O(n*n*2^n)。


代码:


#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define LL long long
#define pb push_back
#define pa pair<int,int>
#define clr(a,b) memset(a,b,sizeof(a))
#define lson lr<<1,l,mid
#define rson lr<<1|1,mid+1,r
#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)
#define key_value ch[ch[root][1]][0]
#define bitnum(a) __builtin_popcount(a)
#pragma comment(linker, "/STACK:102400000000,102400000000")
const LL  MOD = 1000000007;
const int N = 1e5+15;
const int maxn = 8e3+15;
const int letter = 130;
const LL INF = 1e18;
const double pi=acos(-1.0);
const double eps=1e-10;
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
LL dp[1<<18][18],a[18];
int n,vs[18];
int main(){
    int T,p,cas=0;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        clr(vs,-1);
        for(int i=0;i<n;i++){
            scanf("%I64d%d",a+i,&p);
            if(p!=-1)vs[p]=i;
        }
        for(int i=0;i<(1<<n);i++)
            for(int j=0;j<n;j++)dp[i][j]=-INF;
        ///init
        if(vs[0]!=-1) dp[1<<(vs[0])][vs[0]]=0;
        else for(int i=0;i<n;i++) dp[1<<i][i]=0;
        for(int i=1;i<(1<<n);i++){
            for(int j=0;j<n;j++){///j结尾
                if(i&(1<<j)){
                    for(int k=0;k<n;k++){///k没选
                        if((i&(1<<k))==0){
                            int cnt = bitnum(i);
                            if(vs[cnt]==-1||vs[cnt]==k){
                                dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+a[j]*a[k]);
                            }
                        }
                    }
                }
            }
        }
        LL max1=-INF;
        for(int i=0;i<n;i++) max1=max(max1,dp[(1<<n)-1][i]);
        printf("Case #%d:\n%I64d\n",++cas,max1);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值