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;
}
如有问题,求大佬斧正。

浙公网安备 33010602011771号