P4394 [BOI2008]Elect 选举

P4394 [BOI2008]Elect 选举

题目描述
N个政党要组成一个联合内阁,每个党都有自己的席位数.

现在希望你找出一种方案,你选中的党的席位数要大于总数的一半,并且联合内阁的席位数越多越好.

对于一个联合内阁,如果某个政党退出后,其它党的席位仍大于总数的一半,则这个政党被称为是多余的,这是不允许的.

输入输出格式
输入格式:
第一行给出有多少个政党.其值小于等于300

下面给出每个政党的席位数.总席位数小于等于 100000

输出格式:
你的组阁方案中最多能占多少个席位.


一道伪装成紫题其实是黄题的 \(01\) 背包

从大到小排序, 直接背包。这样每次背包完新加进去的都是目前最小的, 可以进行判断。 然后就直接判断是否合法即可

注意判断需要在 \(dp\) 里进行, 这时枚举的 \(i\) 保存了当前数据编号, 才能进行判断

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int RD(){
	int flag = 1, out = 0;char c = getchar();
	while(c < '0' || c > '9'){if(c == '-')flag = -1;c = getchar();}
	while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
	return flag * out;
	}
const int maxn = 100019;
int num;
int a[maxn];
int dp[maxn];
bool cmp(int a, int b){return a > b;}
int sum, ans;
int main(){
	num = RD();
	for(int i = 1;i <= num;i++)a[i] = RD(), sum += a[i];
	sort(a + 1, a + 1 + num, cmp);
	for(int i = 1; i <= num; i++){
		for(int j = sum; j >= 0; j--){
		if(j >= a[i])
			dp[j] = max(dp[j], dp[j - a[i]] + a[i]);
		if(dp[j] > (sum >> 1) && dp[j] - a[i] <= (sum >> 1))
			ans = max(ans, dp[j]);
			}
		}
	printf("%d\n", ans);
	return 0;
	}
posted @ 2018-07-19 17:05  Tony_Double_Sky  阅读(148)  评论(0编辑  收藏  举报