0%

ABC-402-E - Payment Required(酷似背包的状压dp)

思路讲解

我勒个豆,比赛的时候没注意到,这个 N8N\le8。那么其实就很清楚了,状压dp。

首先呢,这个是不能用背包的,这是一个多重背包,乃至于多重都不一定是,因为如果这道题目他做出来了,他就可以不提交了。

状态转移是这样的,如果第 i 个物品在已经做出的题目清单(即状态s)中,那么他可以从已经做出来的状态转移,也可以从没有做出来的状态转移。

dp[x][s]=max((dp[xcost][s(1<<(idx1))]+score)poss+dp[xcost][s](1poss),dp[x][s])dp[x][s]=max({(dp[x-cost][s-(1<<(idx-1))]+score)*poss+dp[x-cost][s]*(1-poss),dp[x][s]})

那么如果不在已经做出的题目清单(即状态s)中,那么只能从没做出来的状态转移过来,即

dp[x][s]=max(dp[x][s],dp[xcost][s](1poss));dp[x][s]=max(dp[x][s],dp[x-cost][s]*(1-poss));

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DB ans=0;
for(int x=1;x<=X;++x){
// 通过的题目集合
for(int s=1;s<=(1<<N);++s){
ll ops=s;
for(int idx=1;idx<=N;++idx){
ll score=Prob[idx][0],cost=Prob[idx][1];DB poss=Prob[idx][2]/100.0;
if(x<cost) {continue;}
if((1<<(idx-1))>s) break;
if((1<<(idx-1)|s)==s ){
dp[x][s]=max({(dp[x-cost][s-(1<<(idx-1))]+score)*poss+dp[x-cost][s]*(1-poss),dp[x][s]});
}else{
// 从没做出来转移过来
dp[x][s]=max(dp[x][s],dp[x-cost][s]*(1-poss));
}
}
ans=max(ans,dp[x][s]);
}
}

AC代码

https://atcoder.jp/contests/abc402/submissions/66038452

心路历程(WA,TLE,MLE……)