当前位置: 首页 > 工具软件 > Eurasia > 使用案例 >

2019-2020 ICPC, NERC, Northern Eurasia Finals E. Elections (暴力&贪心)

狄信然
2023-12-01

2019-2020 ICPC, NERC, Northern Eurasia Finals E. Elections (暴力&贪心)

题意:给定 n n n个候选人, m m m个站点,第 n n n个人是反对候选人,每个站点会有 n n n个人投票个数。

要求删除最少的站使得第 n n n个人的总票数不是严格最多的那个人。

思路:暴力 + + +贪心。

我们的目的是使第 n n n个人不是严格最多的,那么我们就可以假设最后最多的那个人是 g o a l goal goal,然后我们可以暴力枚举 g o a l goal goal对应要删除的站数,然后取最小的即可。

有了 g o a l goal goal我们就很好贪心的删了,我们取所有站的这两个人票数差,然后由大到小取,直到 c n t g o a l ≥ c n t n cnt_{goal}\ge cnt_n cntgoalcntn即可。

时间复杂度: O ( n m l o g m ) O(nmlogm) O(nmlogm)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=105,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define il inline
int n,m;
int a[N][N],sum[N],tmp[N],mn=1e9;
vector<int>ans,res;
struct cha{
	int id;
	int x;
	bool operator<(const cha&c)const{
		return x>c.x; 
	}
}C[N];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			scanf("%d",&a[i][j]);
			sum[j]+=a[i][j];
		}
	}
	for(int i=1;i<=n;i++) tmp[i]=sum[i];
	sort(tmp+1,tmp+n+1);
	if(tmp[n]!=sum[n]||(tmp[n-1]==tmp[n])){
		puts("0");
		puts("");
		return 0;
	} 
	for(int goal=1;goal<n;goal++){
		int sg=sum[goal],sn=sum[n];
		sn-=sg;
		ans.clear();
		for(int i=1;i<=m;i++){
			C[i].x=a[i][n]-a[i][goal];
			C[i].id=i;
		}
		sort(C+1,C+m+1);
		int cnt=0; 
		for(int i=1;C[i].x>0&&i<=m;i++){
			sn-=C[i].x;
			cnt++,ans.pb(C[i].id);
			if(sn<=0) break; 
		}
		if(sn<=0){
		//	printf("goal=%d\n",goal);
			if(ans.size()<mn){
 
				res=ans;
				mn=ans.size();
			}
		}
	}
	printf("%d\n",mn);
	for(int i:res) printf("%d ",i);
	return 0;
}

总结:这种题给了我们一个思考问题的新方向,对于一个问题,我们可以假设答案的结果,然后取依次暴力选取。

 类似资料: