ACM-ICPC 2018 南京賽區網路預賽
阿新 • • 發佈:2018-12-09
題意:
每個作業都有a和b,第i次做這個作業得到的分數為i*a+b。每個作業還可能會有前置作業。
問你最大分數是多少。可以不做。
POINT:
20個作業,可以狀壓。時間就是這個狀態1的個數。
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define LL long long const int N = 20; const LL inf = 0x3f3f3f3f3f3f3f3f; int a[N],b[N],pre[N]; LL dp[1<<N]; int tm[1<<N]; int main() { tm[0]=0; for(int i=1;i<(1<<N);i++){ tm[i]=1+tm[i-(i&-i)]; } int n; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d%d",&a[i],&b[i]); int s;scanf("%d",&s); for(int j=1;j<=s;j++){ int to;scanf("%d",&to); to--; pre[i]|=1<<to; } } for(int i=1;i<(1<<n);i++) dp[i]=-inf; dp[0]=0; LL ans=0; for(int i=0;i<(1<<n);i++){ if(dp[i]==-inf) continue; for(int j=0;j<n;j++){ if((i&(1<<j))==0&&(i&pre[j])==pre[j]){ int to=i|(1<<j); dp[to]=max(dp[to],dp[i]+1LL*(tm[i]+1)*a[j]+b[j]); ans=max(ans,dp[to]); } } } printf("%lld\n",ans); return 0; }