题目描述
多米诺骨牌有上下2个方块组成,每个方块中有1~6个点。现有排成行的
上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|。例如在图8-1中,S1=6+1+1+1=9,S2=1+5+3+2=11,|S1-S2|=2。每个多米诺骨牌可以旋转180°,使得上下两个方块互换位置。 编程用最少的旋转次数使多米诺骨牌上下2行点数之差达到最小。
对于图中的例子,只要将最后一个多米诺骨牌旋转180°,可使上下2行点数之差为0。
输入输出格式
输入格式:
输入文件的第一行是一个正整数n(1≤n≤1000),表示多米诺骨牌数。接下来的n行表示n个多米诺骨牌的点数。每行有两个用空格隔开的正整数,表示多米诺骨牌上下方块中的点数a和b,且1≤a,b≤6。
输出格式:
输出文件仅一行,包含一个整数。表示求得的最小旋转次数。
输入输出样例
输入样例#1:
4 6 1 1 5 1 3 1 2
输出样例#1:
1
状态转移方程
c[i][j]=min(c[i-1][j-d[i]],c[i-1][j+d[i]]+1)
i:前i个骨牌
j:前i个骨牌上下方块点数的差
c[i][j] 表示前i个骨牌上下方块点数差为j的最小旋转次数(所以是min)
d[i]为第i个骨牌上下方块点数的差
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 int a[1002]={0},b[1002]={0},d[1002]={0}; 5 int c[1002][10001]={0}; 6 int min(int a,int b) 7 { 8 if(a>b) 9 return b; 10 else 11 return a; 12 } 13 int main() 14 { 15 memset(c,0x3f,sizeof(c)); 16 int n,i,j,k; 17 cin>>n; 18 for(i=1;i<=n;i++) 19 { 20 cin>>a[i]>>b[i]; 21 d[i]=a[i]-b[i]; 22 } 23 k=1002; 24 c[0][5000]=0; 25 for(i=1;i<=n;i++) 26 for(j=-5000;j<=5000;j++) 27 c[i][5000+j]=min(c[i-1][5000+j-d[i]],c[i-1][5000+j+d[i]]+1); //<-状态转移方程 28 j=5000; 29 while(j<10000) 30 { 31 if((c[n][j]<1000)&&(k>c[n][j])) 32 k=c[n][j]; 33 if((c[n][10000-j]<1000)&&(k>c[n][10000-j])) 34 k=c[n][10000-j]; 35 if(k<1000) 36 break; 37 j++; 38 } 39 cout<<k; 40 return 0; 41 }
原文:https://www.cnblogs.com/zhengyongle506/p/10705062.html