HDU 6709 Fishing Master 容斥+贪心

440人浏览 / 0人评论

题目链接

  • H - Fishing Master
    • 这道题当年打网络赛的时候是想了一个策略的,但是训练时忘了,所以重新从更加数学的角度思考了一下。
    • 思路:我们总共需要n段钓鱼的时间和n段煮鱼的时间,其总和为nk+∑ti。然而我们有重合的部分需要减去,所以实际需要的时间为——nk+∑ti-重合部分。所以问题变成如何求出最大的重合部分,我们知道显然可以完全利用的时间只有煮鱼时间ti中k的整数倍,即ti%k的那一部分时间是注定会有损耗的。一开始没有鱼的时候必须花k的时间去钓一条鱼,所以如果∑(ti/k)≥n-1,总时间就直接是k+n*ti。
    • 如果∑(ti/k)<n-1,那么我们还需要n-1-∑(ti/k)段时间去钓鱼,这些时间就是ti%k的那一部分,注定浪费时间。所以我们贪心地去ti%k最大的几个ti值即可减少浪费。

代码:

#include<cstdio>
#include<algorithm>
using namespace std;
int t[(int)1e5+10];
bool cmp(int a,int b)
{
	return a>b;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		long long n,k;
		scanf("%lld%lld",&n,&k);
		long long cnt=0;
		for(int i=0;i<n;++i)
		{
			scanf("%d",&t[i]);
			cnt+=t[i]/k*k;
		}
		long long sum=0;
		for(int i=0;i<n;++i)
		{
			sum+=t[i];
		}
		if(cnt>=(n-1)*k)
		{
			printf("%lld\n",k+sum);
		}
		else
		{
			for(int i=0;i<n;++i)
			{
				t[i]%=k;
			}
			sort(t,t+n,cmp);
			int red=cnt/k;
			for(int i=0;i<n-1-red;++i)
			{
				cnt+=t[i];
			}
			printf("%lld\n",n*k+sum-cnt);
		}
	}
	return 0;
}

全部评论