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

邮差的信 提交于 2021-01-13 18:37:26

题意:有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;
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!