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
思路
把所有点数大的置上,对于反转过的卡牌,重量为-1,价值为 2 * (Y - X),并增加背包原始重量;未反转的,重量为1, 体积为 2 * (X-Y);
f[i][j] 表示前 i 张牌的体积为 j 的最小重量。
CODE
1 #include <bits/stdc++.h> 2 #define dbg(x) cout << #x << "=" << x << endl 3 #define eps 1e-8 4 #define pi acos(-1.0) 5 6 using namespace std; 7 typedef long long LL; 8 9 template<class T>inline void read(T &res) 10 { 11 char c;T flag=1; 12 while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0'; 13 while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag; 14 } 15 16 namespace _buff { 17 const size_t BUFF = 1 << 19; 18 char ibuf[BUFF], *ib = ibuf, *ie = ibuf; 19 char getc() { 20 if (ib == ie) { 21 ib = ibuf; 22 ie = ibuf + fread(ibuf, 1, BUFF, stdin); 23 } 24 return ib == ie ? -1 : *ib++; 25 } 26 } 27 28 int qread() { 29 using namespace _buff; 30 int ret = 0; 31 bool pos = true; 32 char c = getc(); 33 for (; (c < '0' || c > '9') && c != '-'; c = getc()) { 34 assert(~c); 35 } 36 if (c == '-') { 37 pos = false; 38 c = getc(); 39 } 40 for (; c >= '0' && c <= '9'; c = getc()) { 41 ret = (ret << 3) + (ret << 1) + (c ^ 48); 42 } 43 return pos ? ret : -ret; 44 } 45 46 int n; 47 48 int f[1007][6007]; 49 bool vis[1007][6007]; 50 51 int w[1007]; 52 int v[1007]; 53 54 int main() 55 { 56 int x, y; 57 scanf("%d",&n); 58 int maxn = 0; 59 int weight = 0; 60 for(int i = 1; i <= n; ++i) { 61 scanf("%d %d",&x, &y); 62 if(x > y) { 63 v[i] = 2 * (x-y); 64 w[i] = 1; 65 maxn += x-y; 66 } 67 if(y > x) { 68 v[i] = 2 * (y-x); 69 w[i] = -1; 70 maxn += y-x; 71 weight++; 72 } 73 } 74 for(int i = 1; i <= n; ++i) { 75 for(int j = 1; j <= maxn; ++j) { 76 f[i][j] = f[i-1][j]; 77 vis[i][j] = vis[i-1][j]; 78 if(vis[i-1][j-v[i]] || !(j - v[i])) { 79 if(!vis[i][j]) { 80 f[i][j] = f[i-1][j-v[i]] + w[i]; 81 vis[i][j] = 1; 82 } 83 else { 84 f[i][j] = min(f[i][j], f[i-1][j-v[i]]+w[i]); 85 } 86 } 87 } 88 } 89 int q; 90 for(int i = maxn; i >= 1; --i) { 91 if(vis[n][i]) { 92 q = i; 93 break; 94 } 95 } 96 printf("%d\n",weight+f[n][q]); 97 return 0; 98 }