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\n",ans); return 0; }