1. 程式人生 > 實用技巧 >AtCoder ABC 060 D - Simple Knapsack

AtCoder ABC 060 D - Simple Knapsack

揹包問題。

但 w 的範圍是1e9 ,顯然不能用DP。

考慮到限制w1 ≤ wi ≤ w1 + 3,所以最多隻會有四個不同的重量,統計每個重量的物品數,

然後列舉每個重量選多少個物品,選物品時顯然要貪心地選最大的。

程式碼很醜,也不知道怎麼優化

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace
std; typedef long long ll; const int maxn = 110; int n,cnt; ll W,mi,ans; int cn[10]; ll val[10][maxn],w[maxn],cw[maxn],wei[10],v[maxn],pre[10][maxn]; bool cmp(ll a,ll b){ return a>b; } ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while
(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } int main(){ mi = 1e9 + 7; ans = 0; n = read(),W = read(); for(int i=1;i<=n;i++){ w[i] = read(); cw[i] = w[i]; mi = min(mi, w[i]); v[i] = read(); } sort(cw+1,cw+1+n);
for(int i = 1;i <= n;i++){ if(cw[i] != cw[i-1]){ wei[++cnt] = cw[i]; } } for(int i=1;i<=n;i++){ int nt = w[i]-mi+1; val[nt][++cn[nt]] = v[i]; } for(int i=1;i<=cnt;i++){ sort(val[i]+1,val[i]+1+cn[i],cmp); } for(int i=1 ;i <= cnt;i++){ for(int j = 1 ;j<=cn[i]; j++){ pre[i][j]=val[i][j]; pre[i][j]+=pre[i][j-1]; } } if(cnt==4){ for(int i=0 ;i <= cn[1];i++){ for( int j= 0;j <= cn[2] ;j++){ for( int k=0 ;k <= cn[3] ;k++){ for(int p = 0; p <= cn[4] ; p++){ if(i*wei[1]+j*wei[2]+k*wei[3]+p*wei[4]<=W){ ans =max( pre[1][i] + pre[2][j] + pre[3][k] + pre[4][p],ans); } } } } } } if(cnt==3){ for(int i=0 ;i <= cn[1];i++){ for( int j= 0;j <= cn[2] ;j++){ for( int k=0 ;k <= cn[3] ;k++){ if(i*wei[1]+j*wei[2]+k*wei[3]<=W){ ans =max( pre[1][i] + pre[2][j] + pre[3][k],ans); } } } } } if(cnt==2){ for(int i=0 ;i <= cn[1];i++){ for( int j= 0;j <= cn[2] ;j++){ if(i*wei[1]+j*wei[2]<=W){ ans =max( pre[1][i] + pre[2][j] ,ans); } } } } if(cnt==1){ for(int i=0 ;i <= cn[1];i++){ if(i*wei[1]<=W){ ans =max( pre[1][i] ,ans); } } } printf("%lld\n",ans); return 0; }