首页 > 代码库 > [Poetize I]守卫者的挑战

[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 描述 Description2   打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜寻着关押applepi的监狱的所在地。突然,眼前一道亮光闪过。“我,Nizem,是黑魔法圣殿的守卫者。如果你能通过我的挑战,那么你可以带走黑魔法圣殿的地图……”瞬间,队员们被传送到了一个擂台上,最初身边有一个容量为K的包包。3   擂台赛一共有N项挑战,各项挑战依次进行。第i项挑战有一个属性ai,如果ai>=0,表示这次挑战成功后可以再获得一个容量为ai的包包;如果ai=-1,则表示这次挑战成功后可以得到一个大小为1 的地图残片。地图残片必须装在包包里才能带出擂台,包包没有必要全部装满,但是队员们必须把 【获得的所有的】地图残片都带走(没有得到的不用考虑,只需要完成所有N项挑战后背包容量足够容纳地图残片即可),才能拼出完整的地图。并且他们至少要挑战成功L次才能离开擂台。4   队员们一筹莫展之时,善良的守卫者Nizem帮忙预估出了每项挑战成功的概率,其中第i项挑战成功的概率为pi%。现在,请你帮忙预测一下,队员们能够带上他们获得的地图残片离开擂台的概率。
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 long10 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

 

[Poetize I]守卫者的挑战