1080 国王游戏

1080 国王游戏

首先,需要把题目进行提炼
国王有n个大臣,他们每一个人,左右手各有一个数,ai,bi国王要他们站成一排(国王自己站在前面),随后给每个大臣奖赏
对于每一个大臣如果他前面的人左手上的数乘积是A,他自己右手上的是bi,那么他会获得A/bi的奖赏,国王想要让获得奖赏最多的大臣获得的尽量少,请你安排一种顺序满足他的要求,并输出最多大臣最少获得奖赏
记住一个思路,先考虑入局很小的情况,往往是有帮助的
从而推出公式
如果只有两个大臣,两个大臣的必要条件是,大臣2放在大臣1前面得到的最大值更小,那么我们分别讨论两种情况的最大值
1.如果大臣1在前面,他俩的金币数分别为
a0/b1,a0a1/b2
2.如果大臣2在前面,他俩的金币数分别为
a0/b2,a0
a2/b1
首先我们先约去式子中的a0,然年后分别讨论两种情况的最大值,就变成了比较:
max(1/b1,a1/b2)和max(1/b2,a2/b1)的大小
根据a是正整数的条件,我们可以得出
a1/b2>=1/b2,1/b1<=a2/b1
那么如果1/b1是最大的,那么就有1/b1>=a2/b1只可能左右两边相等,那么就有1/b2<=b2/b1所以两种情况的最大值是一样的,不用交换,变形之后得a1b1>a2b2
所以 ,我们只需要对a*b进行排序就好了
--------重新----------------
这个题很恶心
该大臣的金币数量,排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果
明白题意了
这个国王想搞获得最多的大臣
所以,这个题是什么贪心算法

#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
struct node{
	int a,b;
	char cnta[10000],all[10000];//cnta 为前面所有a的乘积的逆序 all为乘积正序 
	char ca[100];//转化后的字符数组 
	char ans[10000];//金币的数量 
	int lans;
}da[1001];
bool cmp(node a,node b)
{
	return a.a*a.b<b.a*b.b;
}
bool cmp2(node a,node b)
{//高精度比较 
	if(a.lans!=b.lans)
		return a.lans>b.lans;
	else
	{
		int i;
		for(i=0;i<a.lans;i++)
			if(a.ans[i]==b.ans[i])
			 {
				continue;
			}
			else return a.ans[i]>b.ans[i];
	}
	return 1==1;
}
void doit(int a,char b[]){//将数值转化成字符数组
	int lb=0;
	while(a>0){
		b[lb++]=a%10+'0';
		a/=10;
	}
	b[lb]='\0';
}
void add(char c[],char d[],int i){//错位相加 
	int lc=strlen(c),j;
	int jw = 0,tmp;
	for(j=0;j<lc;j++,i++){
		tmp=(d[i]>0?d[i]-'0':0)+c[j]-'0'+jw;
		d[i]=tmp%10+'0';
		jw=tmp/10;
	}
	if(jw){
		d[i++]=jw+'0';
	}
	d[i]='\0';
}
void gc(char a[],char b[],char d[])
{//高乘 
	int la=strlen(a);
	int lb=strlen(b);
	int i,j;
	char c[10000];//记录乘数的每一位乘以被乘数的积 
	for(i=0;i<la;i++)
	{
		int tmp;
		int jw = 0;
		int lc = 0;
		for(j=0;j<lb;j++)
		{
			tmp = (a[i]-'0') * (b[j]-'0') + jw;
			c[lc++] = tmp % 10 + '0';
			jw = tmp / 10;
		}
		if(jw) c[lc++]=jw+'0';
		c[lc]='\0';
		add(c,d,i);
	}
}
void mult(char a[],int b,char c[])
{
	int i=0,tag=0,la=strlen(a),lc=0;
	int d = 0;
	while(i<=la)
	{
		if(b>d)
		{
			d=d*10+a[i++]-'0';
			if(tag) 
				c[lc++]='0';
		}
		else
		{
			c[lc++]=d/b+'0';
			d=d%b;
			d=d*10+a[i++]-'0';
			tag = 1;
		}
	}
	if(tag==0)c[lc++]='0';
	c[lc]='\0';
}
int main()
{
	int n,i,j;
	scanf("%d",&n);
	scanf("%d%d",&da[0].a,&da[0].b);
	for(i=1;i<=n;i++)
	{
		scanf("%d%d",&da[i].a,&da[i].b);
	}
	sort(da+1,da+n+1,cmp);
	doit(da[0].a,da[0].ca); 
	da[0].cnta[0]='1';
	da[0].cnta[1]='\0';
	for(i=1;i<=n;i++)//得到前面大臣左手金币数的乘积的逆序
	{ 
		doit(da[i].a,da[i].ca);
		gc(da[i-1].cnta,da[i-1].ca,da[i].cnta);
	}
	for(i=1;i<=n;i++)//将乘积进行逆转 
	{ 
		int k=0;
		for(j=strlen(da[i].cnta)-1;j>=0;j--)
			da[i].all[k++]=da[i].cnta[j];
		da[i].all[k]='\0';
	}
	for(i=1;i<=n;i++)//获取金币数
	{ 
		mult(da[i].all,da[i].b,da[i].ans);
		da[i].lans = strlen(da[i].ans);
	}
	int ans = 1;
	for(i=2;i<=n;i++)
	{
		if(!cmp2(da[ans],da[i]))
			ans=i;
	}
	printf("%s\n",da[ans].ans);//输出答案的金币数量 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值