[Poetize I]守卫者的挑战

描述 Description
  打开了黑魔法师Vani的大门,队员们在迷宫 般的路上漫无目的地搜寻着关押applepi的监狱的所在地。突然,眼前一道亮光闪过。“我,Nizem,是黑魔法圣殿的守卫者。如果你能通过我的挑战, 那么你可以带走黑魔法圣殿的地图……”瞬间,队员们被传送到了一个擂台上,最初身边有一个容量为K的包包。
  擂台赛一共有N项挑战,各项挑战依 次进行。第i项挑战有一个属性ai,如果ai>=0,表示这次挑战成功后可以再获得一个容量为ai的包包;如果ai=-1,则表示这次挑战成功后可 以得到一个大小为1 的地图残片。地图残片必须装在包包里才能带出擂台,包包没有必要全部装满,但是队员们必须把 【获得的所有的】地图残片都带走(没有 得到的不用考虑,只需要完成所有N项挑战后背包容量足够容纳地图残片即可),才能拼出完整的地图。并且他们至少要挑战成功L次才能离开擂台。
  队员们一筹莫展之时,善良的守卫者Nizem帮忙预估出了每项挑战成功的概率,其中第i项挑战成功的概率为pi%。现在,请你帮忙预测一下,队员们能够带上他们获得的地图残片离开擂台的概率。
题解:
三维DP,只不过下标有负数比较麻烦,无奈写了p(貌似c++用个宏就ok了?)
枚举每个状态,按输赢来递推即可。吐槽一下此题数据是有多弱,按理说应该开20W*2*200的数组,M成翔,改成500*2*200就过了。。。
代码:
 1 var i,j,k,n,l,t,mx:longint;
 2     a,b:array[0..250] of longint;
 3     f:array[0..1,-200..5000,0..200] of double;
 4     ans:double;
 5 begin
 6 read(n);read(l);read(mx);
 7 for i:=1 to n do read(b[i]);
 8 for i:=1 to n do read(a[i]);
 9 f[0,mx,0]:=1.0;t:=0;
10 for i:=1 to n do
11  begin
12  t:=1-t;if(a[i]>0)then inc(mx,a[i]);
13  for j:=-n to mx do
14   for k:=0 to i do
15    begin
16    f[t,j,k]:=f[1-t,j,k]*(100-b[i])/100;
17    if(k>0)then f[t,j,k]:=f[t,j,k]+f[1-t,j-a[i],k-1]*b[i]/100;
18    end;
19  end;
20 for i:=0 to mx do for j:=l to n do ans:=ans+f[t,i,j];
21 writeln(ans:0:6);
22 end.    
View Code

 


 hzwer的做法比较好:

首先因为n最大为200,所以背包容量大于200是没有意义的
所以用f[i][j][k]表示前i场胜j场背包容量k的概率
为了防止容量变成负数
可以对挑战进行排序
代码:
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<set>
 6 #include<vector>
 7 #include<algorithm>
 8 #define inf 1000000000
 9 #define ll long long
10 using namespace std;
11 inline int read()
12 {
13     int x=0,f=1;char ch=getchar();
14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
16     return x*f;
17 }
18 int n,l,K;
19 double f[205][205][205];
20 double ans;
21 struct data{double p;int v;}a[205];
22 bool operator<(data a,data b)
23 {
24 return a.v>b.v;
25 }
26 int main()
27 {
28 //freopen("guard.in","r",stdin);
29 //freopen("guard.out","w",stdout);
30 n=read();l=read();K=read();
31 for(int i=1;i<=n;i++)
32 {
33 scanf("%lf",&a[i].p);
34 a[i].p/=100;
35 }
36 for(int i=1;i<=n;i++)a[i].v=read();
37 sort(a+1,a+n+1);
38 f[0][0][min(K,200)]=1;
39 for(int i=0;i<n;i++)
40 for(int k=0;k<=i;k++)
41 for(int j=0;j<=n;j++)
42 {
43 f[i+1][k][j]+=f[i][k][j]*(1-a[i+1].p);
44 int t=j+a[i+1].v;
45 if(t<0)continue;
46 t=min(t,n);
47 f[i+1][k+1][t]+=f[i][k][j]*a[i+1].p;
48 }
49 for(int i=0;i<=n;i++)
50 for(int j=l;j<=n;j++)
51 ans+=f[n][j][i];
52 printf("%.6lf",ans);
53 return 0;
54 }
View Code

 

posted @ 2014-10-20 18:29  ZYF-ZYF  Views(270)  Comments(0Edit  收藏  举报