第十四届蓝桥杯C++C组 三国游戏 知识点:贪心

219 阅读2分钟

2.三国游戏 - 蓝桥云课 (lanqiao.cn)

视频解析:第十四届蓝桥杯C++C组真题三国游戏_哔哩哔哩_bilibili

视频解析:[蓝桥杯]真题讲解:三国游戏(贪心)_哔哩哔哩_bilibili

思想

拿样例举例,当n等于3的时候,一共就有3个事件: image.png

假设只有第一个事件发生:

那么x,y,z三个国家的士兵数量分别是:1,2,1。 image.png

此时没有任何一个国家的士兵数量大于其他两个国家的士兵数量之和。

我们可以发现,当第2事件,第3事件都独立发生时,都不会有合法情况。

因此我们可以去枚举发生多个事件同时发生的情况,假设第1,2事件同时发生:

此时x国的士兵数量大于y,z两国士兵数量之和,是一个合法情况。 image.png

我们再看三个事件同时发生的情况:

我们发现任意一个国家的士兵之和都没有大于其他两个国家的士兵之和。 image.png

因此,最多只有2个事件同时发生时,满足条件,答案就是2。

题意就是让我们求x[i]>y[i]+z[i]时,最多发生多少个事件。

我们转移一下方程:

x[i](y[i]+z[i])>0x[i]-(y[i]+z[i])>0

我们构造一个数组temp,temp=x[i]y[i]+z[i]temp=x[i]-y[i]+z[i]

现在问题就等价于:

从Temp里面最多挑多少个数,使得最终被选数的和大于0。

如果我们贪心的去考虑,就是即要选的数够多,还要被选数的和大于0,那么我们就尽可能多的去选大于0的数,负数尽可能少的去选,就可以保证是最优策略。

我们给数组排个降序,让大的数在前面,负数在后面,每次都把正数选完再选负数,直到<0为止。

举例说明:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;


int solve(vector<int>& a ,vector<int>& b,vector<int>& c)
{
	int cnt=0; 
	int sum=0;
   vector<int> temp(n);
   
   for(int i=0;i<n;i++)
   {
   	temp[i]=a[i]-(b[i]+c[i]);
   }
   
   sort(temp.begin(),temp.end());
   
  
   for(int i=n-1;i>=0;i--)
   {
   	if(sum+temp[i]>0)
   	{
   	   sum+=temp[i];	
	   cnt++; 
	}
	else
	{
		break;
	}
   }	
return cnt;
}
signed main()
{
	
    cin>>n;
	vector<int>a(n),b(n),c(n);
	for(int i=0;i<n;i++)cin>>a[i];
	
	for(int i=0;i<n;i++)cin>>b[i];
	
	for(int i=0;i<n;i++)cin>>c[i];

	int ans=0;
	ans=solve(a,b,c);
    ans=max(ans,solve(b,a,c));
    ans=max(ans,solve(c,a,b)); 

    if(ans)
    cout<<ans<<endl;
	else cout<<-1<<endl; 
	return 0;
}