链接:点击打开链接
题意:给出两个数组a和b,求变化最少的次数来调换a[i]和b[i]使得∑(a[i]-b[i])的绝对值最小
代码:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int a[1005],b[1005],dp[2][12005];
int main(){
int n,i,j,ans,sum;
while(scanf("%d",&n)!=EOF){
sum=0;
for(i=1;i<=n;i++){
scanf("%d%d",&a[i],&b[i]);
sum+=(a[i]+b[i]);
}
memset(dp[0],INF,sizeof(dp[0])); //dp[i][j]表示到第i个,差是j的最小改变次数
dp[0][6000]=0; //将负数变正
for(i=1;i<=n;i++){
memset(dp[i%2],INF,sizeof(dp[i%2]));
for(j=0;j<=12000;j++){
if(dp[(i-1)%2][j]!=INF){
dp[i%2][j+(a[i]-b[i])]=min(dp[i%2][j+(a[i]-b[i])],dp[(i-1)%2][j]);
dp[i%2][j-(a[i]-b[i])]=min(dp[i%2][j-(a[i]-b[i])],dp[(i-1)%2][j]+1);
}
}
}
for(i=0;i<=sum;i++){ //从平移后的零开始找
if(dp[n%2][6000+i]!=INF||dp[n%2][6000-i]!=INF){
ans=min(dp[n%2][6000+i],dp[n%2][6000-i]);
break;
}
}
printf("%d\n",ans);
}
return 0;
}