版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/smmyy022/article/details/81782587
题解
线性dp,需要一点理解。可以类比背包问题,此时的状态不是背包容量而是差值。
f [i][j]:代表对前 i 个牌在 j 的差值下 最小的翻动数。
有递推式
f [ i ] [ j ] = min( f [ i - 1 ] [ j - (a[i]-b[i]) ]+1 , f [ i - 1 ] [ j - (b[i]-a[i]) ] )
a[],b[] 为上下牌面数
ps: 显然 j 差值可能为负,编程时加个偏移量使之为正即可。
Code
// head file excluded
using namespace std;
int n,m;
const int NN = 5000;// 向后位移 保证差值为正
int f[2][NN*2+1];
int a[1001],b[1001];
int main(){
cin>>n;
int border = 0;
for(int i=1;i<=n;i++) {
cin>>a[i]>>b[i];
border += abs(a[i] - b[i]);
}
memset(f,0x7f,sizeof(f));
f[0][0+NN]=0;
int tar=0,ori = 1;// 两数组交替存储
for(int i=1;i<=n;i++){
tar^=1,ori^=1;
for(int j=-border;j<=border;j++){
f[tar][j+NN] = min( f[ori][NN+j-a[i]+b[i]]+1,
f[ori][NN+j-b[i]+a[i]] );
}
}
int ans;
for(int j=0;j<=border;j++){ // 最小到边缘移动 第一个非INF即可
ans = min( f[n&1][NN+j], f[n&1][NN-j] );
if(ans <= 1000){
cout<<ans<<endl;
break;
}
}
return 0;
}