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

Harris-H發表於2020-10-18

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;
}

總結:這種題給了我們一個思考問題的新方向,對於一個問題,我們可以假設答案的結果,然後取依次暴力選取。

相關文章