感觉还是对背包问题不太熟练。
思路:先把n个卡牌第一层加起来记为sum1,第二层卡牌加起来记为sum2。如果sum1<sum2,就将上下层翻转。使得sum1>sum2。V=sum1-sum2.所以我们就将问题转换成了,背包总体积为V,n个物品,每个物品的价值为1,体积为(a[i]-b[i])*2。求使得剩余体积尽量小的背包问题。
体积会出现负数,所以要加以处理。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
const int maxn=1005;
const int N=6000;
int a[maxn],b[maxn];
int dp[12*maxn];
int v[maxn];
int main()
{
int n,ans=0,sum1=0,sum2=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i],&b[i]);
sum1+=a[i];
sum2+=b[i];
}
if(sum1<sum2){
for(int i=1;i<=n;i++)
a[i]=a[i]^b[i],b[i]=a[i]^b[i],a[i]=a[i]^b[i];
}
for(int i=1;i<=n;i++)
v[i]=(a[i]-b[i])*2;
// sort(v+1,v+1+n);
memset(dp,inf,sizeof(dp));
int V=abs(sum1-sum2);
dp[0+N]=0;
sort(v+1,v+1+n);
for(int i=1;i<=n;i++)
for(int j=V;j>=-5000;j--){
if(inf!=dp[j-v[i]+N]){
dp[j+N]=min(dp[j+N],dp[j-v[i]+N]+1);
}
}
int i;
for(i=V;i>=1;i--)
if(inf!=dp[i+N]) break;
printf("%d",dp[i+N]);
return 0;
}