和第二篇题解有些类似,但完全不相同
DP数组的第一维就是表示每一张牌,第二维表示当前的差值。
这个差值将6000视为分界线,也就是<6000的下面的点数大,>6000的上面的大。
每一张牌都处理出放入后对点数的影响。
最后找答案就是从6000开始向两头找。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=1e6+10;
const int INF=0x3f3f3f3f;
int num,ans;
int dp[1005][12010];
int a[MAXN];
int up,down;
signed main()
{
int n,x,y;
cin>>n;
for (int i=1;i<=n;i++){
cin>>x>>y;
up+=x;
down+=y;
a[i]=2*(y-x);
}
memset(dp,0x3f,sizeof(dp));
dp[0][6000+up-down]=0;
for (int i=1;i<=n;i++){
for (int j=0;j<=12010;j++){
dp[i][j]=min(dp[i][j],min(dp[i-1][j],dp[i-1][j+a[i]]+1));
}
cout<<dp[i][6000]<<endl;
}
for (int i=0;i<=6000;i++){
int ans=INF;
if(dp[n][6000+i]!=INF) ans=min(ans,dp[n][6000+i]);
if(dp[n][6000-i]!=INF) ans=min(ans,dp[n][6000-i]);
if(ans!=INF){
cout<<ans<<endl;
return 0;
}
}
return 0;
}