LG-P4394 [BalticOI 2008]选举 Easy 题解

一道 01 背包的题。

题目概述

我们要从若干党中挑选几个党出来,组成一个联合内阁,使得:

  • 内阁的党的总席位数要越多越好;

  • 阁内党席位总数要超过(已给出的)所有党的席位总数的一半;

  • 当其中席位数最小的党退出之后,其他阁内的党的总席位数要比总席位数的一半要少。

求解

在此题中,每一个党面临的问题只有被选或不被选

这很明显,就是背包 dp。

我们当然是挑选席位数大的党选——这样删去它就不容易会出现阁内席位数仍大于总席位数一半的情况。

然后就是背包的板子了。具体可以见 P1048 采药 背包模板题

如果一个党数量上可以加入阁中,且有一种可行的方法,那么就可以用总数量刷新答案。

最后输出答案即可。

本人觉得这道题的难点仅是理解题目吧。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 100050;
int n;
int a[maxn], dp[maxn], res[maxn];
int sum, ans;

int read ()
{
	int x = 1, s = 0;
	char ch = getchar ();
	while (ch < '0' or ch > '9') {if (ch == '-') x = -1; ch = getchar ();}
	while (ch >= '0' and ch <= '9') {s = s * 10 + ch - '0'; ch = getchar ();}
	return x * s;
}

int main ()
{
	dp[0] = 1;
	n = read ();
	for (int i = 1; i <= n; i++) a[i] = read (), sum += a[i];
	sort (a + 1, a + n + 1);
	for (int i = n; i >= 1; i--) res[i] = res[i + 1] + a[i];
	for (int i = n; i >= 1; i--)
	{
		for (int j = (sum >> 1) + a[i]; j >= max ((sum >> 1) - sum + res[i], a[i]); j--) 
			if (dp[j - a[i]])
			{
				dp[j] = 1;
				ans = max (ans, j);
			}
	}
	printf ("%d\n", ans);
	return 0;
}

如有问题,求大佬斧正。

posted @ 2022-03-25 07:25  pldzy  阅读(24)  评论(0)    收藏  举报