原题链接
~~~~~
总题单链接
~~~~~
发现上行的数与下行的数只和不变,所以设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 考虑了前
i
i
i 个牌,且上行的数之和为
j
j
j 的最小旋转数。
if(j>=c[i].fir)dp[i][j]=min(dp[i][j],dp[i-1][j-c[i].fir]);
if(j>=c[i].sec)dp[i][j]=min(dp[i][j],dp[i-1][j-c[i].sec]+1);
转移就是这样,不难理解。
#include<bits/stdc++.h>
#define ll long long
#define fir first
#define sec second
#define INF 0x3f3f3f3f3f3f3f
using namespace std;
pair<ll,ll>c[1005];
ll n,dp[1005][6006],mi=INF,mk,sum;
signed main(){
// freopen("code.in","r",stdin);
// freopen("code_2.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n;
for(ll i=1;i<=n;i++){
cin>>c[i].fir>>c[i].sec;
sum+=c[i].fir+c[i].sec;
}
for(ll i=0;i<=1000;i++)
for(ll j=0;j<=6000;j++)
dp[i][j]=INF;
dp[0][0]=0;
for(ll i=1;i<=n;i++)
for(ll j=0;j<=6*n;j++){
ll d=c[i].fir-c[i].sec;
if(j>=c[i].fir)dp[i][j]=min(dp[i][j],dp[i-1][j-c[i].fir]);
if(j>=c[i].sec)dp[i][j]=min(dp[i][j],dp[i-1][j-c[i].sec]+1);
}
for(ll j=0;j<=n*6;j++){
if(dp[n][j]==INF)continue;
ll x=j,y=sum-x;
if(abs(x-y)<mi)
mi=abs(x-y),mk=dp[n][j];
else if(abs(x-y)==mi)mk=min(mk,dp[n][j]);
}
cout<<mk<<endl;
return 0;
}
还有一件事~(老爹音)
为什么不能设 d p [ i ] [ j ] dp[i][j] dp[i][j] 为考虑了前 i i i 个牌,交换 j j j 次后的上层之和和下层之和的差值的绝对值的最小值?
可以看看这个例子:
3
4 1
3 1
2 4
侵权不究