题解 P4664 【[BalticOI 2008]选举 Hard】
CodyTheWolf · · 题解
提供一个比较不一样的背包解法:(时空都是
当第
(其中
这个是很显然的
对于一个确切的
其实就是变形一下:
(左边要大于等于
考虑暴力,我们只用枚举
我们突然发现,好像可以不枚举这个
4
1 3 2 4
他们分别对应的最大
6 9 7 8
在最后一个4的时候,它可以和3组成7,这是合法的,答案也是这个。
但是按照01背包,他和1、2组成7也是可以的,但是这里的问题是,1的最大
现在问题变成了,有一堆物品,有重量,但是某些物品在背包重量大于等于某个值的时候是非法的。要解决这个问题也很简单,因为我们的不等式太简单了。
只要按“对应的最大
最后一个问题就是输出方案的问题:其实我们上面的背包只用记录存不存在就可以了,这个背包是没有类似标准01背包那样还有价钱的。我们只用在背包的权值处记录这个重量其实是加了某个物品
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
const int MAXN=305,MAXT=1e5+5;
pii a[MAXN];//(结构体都懒得写.jpg)
int bag[MAXT];
int ans[MAXN],tail;
int n,s,mx;
signed main(void)
{
cin>>n;
for(int i=1,x;i<=n;i++) scanf("%d",&x),s+=x,a[i]={x,i};
sort(a+1,a+n+1),bag[0]=n+1;
for(int i=n;i>=1;i--)
for(int k=s/2+a[i].first;k>=a[i].first;k--)
if(bag[k-a[i].first]&&!bag[k]) bag[k]=i;
for(int i=1e5;i>=0;i--)
if(bag[i]) {mx=i;break;}
while(mx) ans[++tail]=a[bag[mx]].second,mx=mx-a[bag[mx]].first;
printf("%d\n",tail);
for(int i=1;i<=tail;i++) printf("%d ",ans[i]);
return 0;
}