1. 程式人生 > >LUOGU P4394 [BOI2008]Elect 選舉 (揹包)

LUOGU P4394 [BOI2008]Elect 選舉 (揹包)

傳送門

解題思路

  一眼看上去就像個揹包,然後就是\(0/1\)揹包改一改,結果發現過不了樣例。後來想了一下發現要按\(a\)從大到小排序,因為如果對於一個>=總和的一半但不滿足的情況來說,把最小的去掉也一定>=總和的一半。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

using namespace std;
const int MAXN = 305;

inline int rd(){
    int x=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x;
} 

int n,f[MAXN][100005],a[MAXN],Sum;
 
inline bool cmp(int x,int y){
    return x>y;
} 
 
int main(){
    n=rd();
    for(int i=1;i<=n;i++) a[i]=rd(),Sum+=a[i];
    sort(a+1,a+1+n,cmp);
    f[0][0]=1;
    for(int i=1;i<=n;i++)
        for(int j=0;j<=Sum;j++){
            f[i][j]|=f[i-1][j];
            if(j>=a[i] && j-a[i]<=Sum/2) f[i][j]|=f[i-1][j-a[i]]; 
        }
    for(int i=Sum;i;i--) 
        if(f[n][i]) {printf("%d",i);return 0;}
}