[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.

 

posted @ 2015-05-05 20:37  mjy0724  阅读(260)  评论(0编辑  收藏  举报