ACM-ICPC 2018 南京赛区网络预赛 E. AC Challenge (状压dp)

题意:有N个问题,解决问题i之前要先解决si个问题;每分钟只能解决一个问题;每分钟必须解决一个问题,否则比赛结束。结束时获得的得分是\(\sum_{}{ai*t+bi}\),i是解决的问题编号,t是解决该问题的时间。
分析:N不超过20,将解决问题的情况状压,用数组dp[i][s]表示第i个问题为最后解决的问题时,s解决问题为s的状态下的最高得分。而i这一维是会被覆盖的所以可以略去。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long LL;
struct Node{
    LL a,b;
}vz[25];
LL dp[(1<<20)];
vector<int> G[25];

LL getnum(int x)
{
    LL ans=0;
    while(x){
        if(x&1) ans++;
        x>>=1;
    }
    return ans;
}

bool check(int s,int i)
{
    if((s&(1<<i))==0) return false;
    if(dp[s^(1<<i)]==-1) return false;
    for(auto &t :G[i]){
        if((s&(1<<t))==0) return false;
    }
    return true;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int N; 
    while(scanf("%d",&N)==1){
        memset(dp,-1,sizeof(dp));
        for(int i=0;i<=N;++i)  G[i].clear();
        for(int i=0;i<N;++i){
            int u,v,t;
            scanf("%lld %lld %d",&vz[i].a,&vz[i].b,&t);
            while(t--){
                scanf("%d",&u); u--;
                G[i].push_back(u);
            }
        }
        LL res=0;
        int all = (1<<N)-1;
        dp[0] =0;
        for(int sta=1;sta<=all;++sta){
            for(int i=0;i<N;++i){
                if(check(sta,i)){
                    dp[sta] = max(dp[sta],dp[sta^(1<<i)]+vz[i].a*getnum(sta)+vz[i].b);
                    res = max(res,dp[sta]);
                }
            }
        }
        printf("%lld\n",res);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xiuwenli/p/9573228.html