P1282 多米诺骨牌

题目描述
多米诺骨牌有上下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 }

 

posted @ 2019-04-14 14:27  ◆◇dear丶妖孽╮ゞ  阅读(123)  评论(0编辑  收藏  举报
……
芋、头、sleepwalking、…