社区讨论

求助简单期望dp

P2473[SCOI2008] 奖励关参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@lozuvytg
此快照首次捕获于
2023/11/15 22:26
2 年前
此快照最后确认于
2023/11/16 10:42
2 年前
查看原帖
先拜谢大佬 orz
不是很理解倒推时候那个最优化转移,但是这么正着写不对,感觉是最优化转移的地方锅了:
CPP
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
#include <unordered_map>
#include <algorithm> 

using std::cin;
using std::cout;
using LL = long long;
using ld = long double;
using ull = unsigned long long;

ld f[110][1<<15]; // 期望最大得分
ld p[110][1<<15]; // 抵达某个状态的概率

int k,n;
int req[16],w[16]; // 宝物依赖(mask),得分

int main(){
	cin >> k >> n;
	for(int i=1,x;i<=n;i++){
		cin >> w[i] >> x;
		while(x) req[i] |= 1<<(x-1), cin >> x;
	}
	
	f[0][0]=0, p[0][0]=1;
	for(int i=0;i<k;i++){
		for(int S=0;S<(1<<n);S++){ // 前一个为S 向i转移
			for(int j=1;j<=n;j++){ // 转移时掉落了 j 物品
				if((req[j] & S) == req[j]){
					if(f[i][S]+w[j]*p[i][S] > f[i][S|(1<<(j-1))]){ // 比不选的朴素转移优,然后选;
						p[i+1][S|(1<<(j-1))]+=p[i][S]/n;
						f[i+1][S|(1<<(j-1))]+=(f[i][S]+w[j]*p[i][S])/n;
					}
					else p[i+1][S]+=p[i][S]/n, f[i+1][S]+=f[i][S]/n; // 没选;
				}
				else p[i+1][S]+=p[i][S]/n, f[i+1][S]+=f[i][S]/n; // 不能选;
			}
		}
	}
	ld ans=0;
	for(int S=0;S<(1<<n);S++) ans+=f[k][S];
	printf("%.6Lf",ans);
	return 0;
} 
题解这个倒着的转移为啥只用max就能实现最优化啊???后效性啥的不会有影响吗?而且不少期望题也能正推啊(比如换教室那种)??
(确实是没能get到那个逆推的精髓。。。)
CPP
for (i = K; i >= 1; i--) for (j = 0; j < (1 << n); j++) {
	for (k = 1; k <= n; k++) if ((j & sta[k]) == sta[k])
		f[i][j] += max(f[i + 1][j], f[i + 1][j | (1 << k - 1)] + p[k]);
	else f[i][j] += f[i + 1][j];
	f[i][j] /= n;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...