UVALive - 7527 Funfair (动态规划)

题目链接:

uva live 或     vjudge


题目大意: 给出n场比赛,其中第i场获胜的概率是 pi,获胜所得金钱为Ai,失败损失当前已拥有的金钱的Li/100

最初有x0的金钱,现在要在n场比赛中选择k场比赛,求问如何选择比赛及安排比赛顺序使得最终剩余的 期望金钱最多。

     

题目分析: 

两个问题: 1.选择比赛   2.安排比赛顺序

艾神一说推公式我就想到国王游戏(noip2012)了.......

套路与那道noip水题一致:

我们假设现在已经确定了要打哪k场比赛,那么现在的目的就是对这k场比赛进行排序使得最终期望金钱最多

排序的基本操作就是比较和交换。

有了国王游戏的经验,我们直接来考虑交换:

交换当前的比赛序列中相邻的两场比赛对这两场比赛之前的期望得分没有任何的影响

那就考虑如何安排这两场比赛的顺序可以使得期望得分最高

对于i和j两场比赛也就只有(i,j)和(i,j)这两种情况了,类比国王游戏推推公式代入比较函数中进行 排序就好了。

  要注意的是,国王游戏的参数很少容易推知,而此题有li,ai,pi三个参数,初始的式子复杂晦涩,那不妨先忍痛将括号划开,尽力相消,之后将只与i有关的参数放在一起看做一个或两个属性,亲自尝试发现这样做后式子就变成了两个很简单的一元一次式。

推导过程还是自己做的好,不然懒癌发作岂不吃枣药丸(我才不会承认是我懒癌发作懒得再写一遍)

'


代码:














#include<bits/stdc++.h>
#define N 202
#define eps 1e-4
using namespace std;
struct node
{
	int a;double l,p;
	double x,y;
}p[N];
bool operator < (node a,node b)
{
	return a.x*(b.y-1)>(a.y-1)*b.x;
}
int n,k,s;
double f[N][N];
void solve()
{
	f[0][0]=s;
	for(int i=1;i<=n;i++)
		for(int j=0;j<=min(i,k);j++)
		{
			f[i][j]=f[i-1][j];
			if(j)
			{
				double ss=f[i-1][j-1];
				f[i][j]=max(f[i][j],p[i].x+ss*p[i].y);
			}
		}
}
/*
2 2 100
10 0 50
100 10 20
2 1 100
10 0 50
100 10 20
0 0 0
*/
int main()
{
	while(~scanf("%d%d%d",&n,&k,&s))
	{
		if(!(n||k||s))break;
		memset(f,0,sizeof(f));
		for(int i=1;i<=n;i++)
		{
			int x,y;
			scanf("%d%d%d",&p[i].a,&x,&y);
			p[i].l=(x+0.0)/100.0,p[i].p=(y+0.0)/100.0;
			p[i].x=p[i].p*p[i].a,p[i].y=p[i].l*(p[i].p-1)+1;
		}sort(p+1,p+1+n);
		solve();
		printf("%.2lf\n",f[n][k]);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值