洛谷P1282 多米诺骨牌

每个骨牌上下相差最多为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)

最后答案就是上下差值最小对应的旋转次数。

猜你喜欢

转载自blog.csdn.net/Wen_Yongqi/article/details/85105495