每个骨牌上下相差最多为6-1=5,1000个骨牌最多相差5000,考虑正负,偏移5000,可以开10000大小的数组存上下差值
设f(i,j):前i个骨牌,上比下多j-5000个对应的最少旋转次数。
f(0,5000)=0,f(0,j)=inf
f(i,j)=min{f(i-1,j-(a[i]-b[i])),f(i-1,j-(b[i]-a[i]))+1}
最后看前n个骨牌在5000附近最近的可行的差值对应的旋转次数。
#include<bits/stdc++.h>
using namespace std;
int n,a[1005],b[1005];
int f[1005][10005];
int main()
{
freopen("input.in","r",stdin);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i]>>b[i];
fill(f[0],f[0]+10005,(1<<30));
f[0][5000]=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=10000;j++)
{
f[i][j]=(1<<30);
int last1=j-(a[i]-b[i]),last2=j-(b[i]-a[i]);
if(last1>=0&&last1<=10000)f[i][j]=min(f[i][j],f[i-1][last1]);
if(last2>=0&&last2<=10000)f[i][j]=min(f[i][j],f[i-1][last2]+1);
}
}
for(int i=0;;i++)
{
int j1=5000+i,j2=5000-i;
if(f[n][j1]<(1<<30)||f[n][j2]<(1<<30))
{
cout<<min(f[n][j1],f[n][j2])<<endl;
break;
}
}
return 0;
}
看题解,有另一种状态表示方法:
f(i,j):前i个骨牌,第一行和为j时的最少旋转次数。因为前i个骨牌上下之和是确定的,所以有上边的和,下边的和还有差值就有了。
f(0,0)=0 f(0,j)=inf
f(i,j)=min(f(i-1,j-a[i]),f(i-1,j-b[i])+1)
最后答案就是上下差值最小对应的旋转次数。