CF1267G Game Relics

Description

Esports is a form of competitive sports using video games. Dota 2 is one of the most popular competitive video games in Esports. Recently, a new video game Dota 3 was released. In Dota 3 a player can buy some relics for their hero. Relics are counters that track hero's actions and statistics in a game.

Gloria likes to play Dota 3, so she wants to buy all $n$ available relics for her favorite hero.

Relics can be bought using an in-game currency called shards. Each relic has its own price ¡ª $c_i$ shards for the $i$ -th relic. A player can buy a relic using one of the following options:

Pay $c_i$ shards to buy the $i$ -th relic;
Pay $x$ shards and randomly get one of all $n$ relics. The probability of getting a relic is the same for all $n$ relics. If a duplicate relic is received, then the relic is recycled and $frac{x}{2}$ shards are given back to the player.
Gloria wants to buy all $n$ relics. Help her minimize the expected number of shards she spends to buy all the relics.

Solution

发现一定是先抽再买是最优的

如果已经抽到$i$张,抽到下一张的期望花费为$(frac {n}{n-i} +1)frac x2$,最后一次的花费不返还

因为购买一定在最后,所以当剩余牌的总代价为$c$,张数为$i$时,可以视为每抽到一张的期望代价是$frac ci$

对于每一种情况取最小的代价转移

#include<iostream>
#include<cstdio>
using namespace std;
int n;
double dp[107][10007],ans,x,c[107],s;
inline int read(){
    int f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
    return f*w;
}
int main(){
    n=read(),x=read(),dp[0][0]=1;
    for(int i=1;i<=n;i++)c[i]=read(),s+=c[i];
    for(int i=1;i<=n;i++)for(int j=n;j;j--)for(int k=c[i];k<=s;k++)dp[j][k]+=dp[j-1][k-(int)c[i]]*j/(n-j+1);
    for(int i=1;i<=n;i++)for(int j=1;j<=s;j++)ans+=dp[i][j]*min((n+i)*x/2,1.0*j)/i;
    printf("%.10lf
",ans);
    return 0;
}
Game Relics
原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14342065.html