洛谷 P1282 多米诺骨牌 [ 分组背包(每组有且只能选一个) ]
https://www.luogu.com.cn/problem/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
1 | 4 |
输出 #1
1 | 1 |
要差值最小,就是填一个 sum/2 的背包…然后每组有且只能必须选择一个加入,转移方程:$d[i][j]=max(d[i-1][j-c_i]+w_i)$
这样只能求得最小差值,题目要求差值最小的情况下旋转次数也最少,所以用 $c[i][j]$ 记录前 i 个骨牌容量为 j 的情况下最少的旋转次数,代价相等的情况下有
$c[i][j]=min(c[i-1][j-c_0],c[i-1][j-c_1] + 1)$
$c_0,c_1$ 表示当前骨牌上下点数。
然后需要注意的是,下标越界… 容量为 0 初始化为 -INF ,即:$d[i][0]=-INF$(
调了好久,菜哭)sum 可能是奇数,sum/2 取大的!考虑这样的情况,$pre + c_1 = sum/2 , pre + c_1 = sum/2 + 1$
这样取小的话旋转次数就多 1 。所以取大
1 | const int INF=0x3f3f3f3f; |
放一下大佬的解法 P1282 多米诺骨牌 P1282 多米诺骨牌 题解
蒟蒻想不到就是了…