0%

P2473 [SCOI2008] 奖励关

思路讲解

从这道题目过来的。

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

其实还是有挺多不大一样的地方。

参考这篇题解。

https://www.luogu.com.cn/article/8f5nvjkq

这个主要难度还是在怎么样理解这个倒序遍历上面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
for(int k=K;k>=1;--k){	// 倒过来枚举,因为正过来不一定有合法转移
for(int s=0;s<(1<<N);++s){ // s为获得的宝物清单
for(int idx=1;idx<=N;++idx){ // idx为这一轮获得的宝物编号
ll idx_=idx-1;
bool canTran=true;
FOR(i,0,SZ(g[idx])-1){
if((s|(1<<(g[idx][i]-1)) ) == s){ // | 以后没起作用说明s里包括了
canTran=true;
}else{ // 如果前提条件中有东西是不存在在
canTran=false;
break;
}
}
if(canTran){
dp[k][s]+=max(dp[k+1][s|(1<<idx_)]+scr[idx],
dp[k+1][s]);
}else{
// 相当于白获得了。
dp[k][s]+=dp[k+1][s];
}
}
dp[k][s]/=N;
}
}
cout<<setprecision(6)<<fixed<<dp[K][0]<<"\n";

不过我们也可以作死,试一试正序遍历,其实也没有什么太大问题。

https://www.luogu.com.cn/record/218153981

那么如何理解dp[K][0]是

AC代码

https://www.luogu.com.cn/record/218152633

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