计蒜客 30994 - AC Challenge - [状压DP][2018ICPC南京网络预赛E题]
Posted dilthey
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计蒜客 30994 - AC Challenge - [状压DP][2018ICPC南京网络预赛E题]相关的知识,希望对你有一定的参考价值。
题目链接:https://nanti.jisuanke.com/t/30994
样例输入:
5 5 6 0 4 5 1 1 3 4 1 2 2 3 1 3 1 2 1 4
样例输出:
55
样例输入:
1 -100 0 0
样例输出:
0
题解:
把n道题目做了或者没做作为状态,裸的状压DP。
其中当前的时间 t,就是当前做了的题目数量加上1。
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll INF=1e18; const int maxn=22; int n; struct P{ ll a,b; int pre; }p[maxn]; ll dp[1<<maxn]; int main() { cin>>n; for(int i=1,s;i<=n;i++) { scanf("%lld%lld",&p[i].a,&p[i].b); scanf("%d",&s); p[i].pre=0; for(int j=1,o;j<=s;j++) { scanf("%d",&o); p[i].pre=p[i].pre|(1<<(o-1)); } } //for(int i=1;i<=n;i++) printf("%lld %lld %d ",p[i].a,p[i].b,p[i].pre); for(int sta=0;sta<(1<<n);sta++) dp[sta]=-INF; dp[0]=0; ll ans=0; for(int sta=0;sta<(1<<n);sta++) { if(dp[sta]==-INF) continue; ll t=1; for(int i=1;i<=n;i++) if(sta&(1<<(i-1))) t++; for(int i=1;i<=n;i++) { if(sta&(1<<(i-1))) continue; if(p[i].pre==0 || (p[i].pre&sta)>=p[i].pre) { int nxt=sta|(1<<(i-1)); dp[nxt]=max(dp[nxt],dp[sta]+t*p[i].a+p[i].b); ans=max(dp[nxt],ans); } } } cout<<ans<<endl; }
时间复杂度 $Oleft( {2^n cdot n} ight)$,n = 20 时为2e7,1s足够。
以上是关于计蒜客 30994 - AC Challenge - [状压DP][2018ICPC南京网络预赛E题]的主要内容,如果未能解决你的问题,请参考以下文章