[BZOJ1076][SCOI2008]奖励关解题报告|状压DP
你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关。在这个奖励关里,系统将依次随机抛出k次宝物,每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的宝物以后也不能再吃)。 宝物一共有n种,系统每次抛出这n种宝物的概率都相同且相互独立。也就是说,即使前k-1次系统都抛出宝物1(这种情况是有可能出现的,尽管概率非常小),第k次抛出各个宝物的概率依然均为1/n。 获取第i种宝物将得到Pi分,但并不是每种宝物都是可以随意获取的。第i种宝物有一个前提宝物集合Si。只有当Si中所有宝物都至少吃过一次,才能吃第i种宝物(如果系统抛出了一个目前不能吃的宝物,相当于白白的损失了一次机会)。注意,Pi可以是负数,但如果它是很多高分宝物的前提,损失短期利益而吃掉这个负分宝物将获得更大的长期利益。 假设你采取最优策略,平均情况你一共能在奖励关得到多少分值?
其实题目有个地方刚开始没看懂...
刚开始说了你必须在跑出下一个宝物之前做出选择,然后我以为和执行最优策略矛盾了...
事实上你所得到的都是期望得分
必须在跑出下一个宝物之前作出选择,是因为游戏的具体过程是由系统操作的我们不清楚
而执行最优策略只要在系统执行的一些概率条件下 作出能够得到最大期望得分的操作
我们考虑倒序DP
枚举当前是哪一轮,以及作出选择之前n个数取与不取的状态是怎样的
再枚举这一轮系统抛下的宝物是哪一件
如果满足这个宝物可以取,就在取与不取之间作取舍,如果不可以取,就只能不取
最后再思考一个问题
题目中有一句话“现在决定不吃的宝物以后也不能再吃”,这个限制在DP过程中并没有体现
另外要注意,这个条件限制存在仅当目前这个宝物可以吃,也就是我们有自主选择的权利
然而仔细想一想便可知是不存在问题的
因为当前可以吃的宝物,以后一定也可以吃,因为已经满足了前提宝物集合的条件
然而现在吃掉,在以后还可以吃一些前提宝物集合为当前宝物的宝物
所以当前吃掉一定比以后吃掉的策略要优秀
所以在执行最优决策的过程中是不存在现在不吃以后吃的情况的~
1 program bzoj1076; 2 const maxn = 110;maxm = 32768; 3 var i,k,n,x,j,p:longint; 4 w:array[-1..maxn]of longint; 5 a:array[-1..20,-1..20]of longint; 6 vis:array[-1..20,-1..maxm]of boolean; 7 f:array[-1..maxn,-1..maxm]of extended; 8 9 function ok(x,y:longint):boolean; 10 var i:longint; 11 tmp:array[-1..20]of longint; 12 begin 13 for i:=1 to n do tmp[i]:=y >> (n-i) and 1; 14 for i:=1 to a[x,0] do if tmp[a[x,i]]=0 then exit(false); 15 exit(true); 16 end; 17 18 function max(a,b:extended):extended; 19 begin 20 if a>b then exit(a) else exit(b); 21 end; 22 23 begin 24 readln(k,n); 25 fillchar(a,sizeof(a),0); 26 for i:=1 to n do 27 begin 28 read(w[i]); 29 read(x); 30 while x<>0 do 31 begin 32 inc(a[i,0]); 33 a[i,a[i,0]]:=x; 34 read(x); 35 end; 36 readln; 37 end; 38 for i:=1 to n do 39 for j:=0 to 1 << n-1 do vis[i,j]:=ok(i,j); 40 for i:=k downto 1 do //i表示当前进行到第i轮 41 for j:=0 to 1 << n-1 do //n件物品取与不取的状态 42 begin 43 for p:=1 to n do if vis[p,j] then f[i,j]:=f[i,j]+max(f[i+1,j],f[i+1,j or (1 << (n-p))]+w[p]) else f[i,j]:=f[i,j]+f[i+1,j]; 44 f[i,j]:=f[i,j]/n; 45 end; 46 writeln(f[1,0]:0:6); 47 end.