宁夏邀请赛H
题意:
一个人去打n只怪兽,每只怪兽有HP值和ATK值,分别表示血量与对人造成的伤害,每次打的时候活着的所有怪兽都会对人造成伤害,对于一只怪兽来说,人第i次打它HP下降i。问人打完所有怪兽受到的最小伤害为多少。
思路:
打的次数事实上与HP并不是正相关的,所以要先算出每只怪兽要打几次。
考虑两只怪兽的时候,设打的次数分别为h1和h2,ATK值分别为a1和a2,要使先打第一只怪兽受到的伤害比较小,则有h1(a1+a2)+h2a2<h2(a1+a2)+h1a1,化简后变成h1/a1<h2/a2。
所以要按打的次数/ATK值从小到大排序。
代码:
typedef long long ll;
struct node
{
ll hp,atk;
double val;
}a[100010];
ll suf[100010];
ll f[100010];
bool cmp(node x,node y)
{
return x.val<y.val;
}
int init()
{
int num;
f[1]=1;
for(int i=2;;i++)
{
ll temp=(ll)i;
f[i]=temp*(temp+1)/2;
if(f[i]>=100000)
{
num=i;
break;
}
}
/*for(int i=1;i<=num;i++)
printf("%lld ",f[i]);
printf("\n");*/
return num;
}
int main()
{
int t,n,num;
scanf("%d",&t);
num=init();
for(int kase=1;kase<=t;kase++)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&a[i].hp,&a[i].atk);
int pos=lower_bound(f+1,f+num+1,a[i].hp)-f;
a[i].hp=pos;
a[i].val=1.0*a[i].hp/a[i].atk;
}
sort(a+1,a+n+1,cmp);
suf[n+1]=0;
for(int i=n;i>=1;i--)
suf[i]=suf[i+1]+a[i].atk;
ll ans=0;
for(int i=1;i<=n;i++)
ans+=a[i].hp*suf[i];
printf("Case #%d: %lld\n",kase,ans);
}
return 0;
}
计蒜之道复赛A
题意:
给你n个一次函数,给出一个x,让你嵌套成一次函数的形式,一次函数可以任意改变顺序,求的最大值。
思路:
同样是考虑两个变量的时候,设有,要使,化简得到。所以按从小到大排序,从里到外计算即可。
代码:
struct node
{
int a,b;
}num[10010];
bool cmp(node x,node y)
{
return 1.0*(1-x.a)/x.b>1.0*(1-y.a)/y.b;
}
int main()
{
int t,n,x;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&x);
for(int i=0;i<n;i++)
scanf("%d",&num[i].a);
for(int i=0;i<n;i++)
scanf("%d",&num[i].b);
sort(num,num+n,cmp);
int ans=x;
for(int i=0;i<n;i++)
{
ans=((ans*num[i].a)+num[i].b)%10;
//printf("%d\n",ans);
}
printf("%d\n",ans);
}
return 0;
}
总结
这两道题目都是从两项入手算出来的,而且这种条件是传递的。这是考虑贪心问题的一种方向。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!