[luoguP1282] 多米诺骨牌(DP + 背包)

传送门

将问题转换成分组背包,每一组有上下两个,每一组中必须选则一个,上面的价值为0,下面的价值为1,求价值最小

因为要求上下两部分差值最小,只需从背包大小为总数 / 2 时往前枚举,找最小答案即可。

——代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define N 100001
 5 #define min(x, y) ((x) < (y) ? (x) : (y))
 6 #define max(x, y) ((x) > (y) ? (x) : (y))
 7
 8 int n, m, tot, ans;
 9 int a[N], b[N], f[N];
10
11 inline int read()
12 {
13     int x = 0, f = 1;
14     char ch = getchar();
15     for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = -1;
16     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - ‘0‘;
17     return x * f;
18 }
19
20 int main()
21 {
22     int i, j, tmp;
23     n = read();
24     memset(f, 127 / 3, sizeof(f));
25     for(i = 1; i <= n; i++)
26     {
27         tot += a[i] = read();
28         tot += b[i] = read();
29         m += max(a[i], b[i]);
30     }
31     f[0] = 0;
32     for(i = 1; i <= n; i++)
33         for(j = m; j >= 0; j--)
34         {
35             tmp = 1e9;
36             if(j >= a[i]) tmp = min(tmp, f[j - a[i]]);
37             if(j >= b[i]) tmp = min(tmp, f[j - b[i]] + 1);
38             f[j] = tmp;
39         }
40     for(i = tot >> 1;;i--)
41     {
42         ans = min(f[i], f[tot - i]);
43         if(ans < 1e9)
44         {
45             printf("%d\n", ans);
46             return 0;
47         }
48     }
49 }

时间: 2024-11-07 19:17:07

[luoguP1282] 多米诺骨牌(DP + 背包)的相关文章

ZOJ 3650(多米诺骨牌 dp + 线段树优化)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3650 题意: 给你n个骨牌,每个骨牌有一个在x轴上的位置和高度,每个骨牌可以想左推也可以向右推,问最少多少步可以把骨牌全部推倒. 思路: 之前Goodbye 2014 上的E题就是一道多米诺骨牌的题目,虽然跟这道题目不太一样但是还是提供了一下思路, 附题解的链接: http://blog.csdn.net/u013649253/article/details/4

洛谷 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. 输入输出格式 输入格式: 输入文件的第一行是一个正

P1282 多米诺骨牌

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. 输入输出格式 输入格式:

luogu 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. 输入输出格式 输入格式: 输入文件的第一行是一个正

状态压缩动态规划 -- 多米诺骨牌

用1*2 的骨牌通过组合拼成 m * n 的大矩形,问有几种拼法. 题目链接:http://poj.org/problem?id=2411 状态转移: 1.由于上一行的该列竖直放置骨牌为 0,影响到当前行的该列,当前行的该列为 1 2.当前行骨牌横放,上一行骨牌横放, 都为11 3.上一行该列置为 1,当前行当前列立着放为 0 #include <iostream> #include <cstring> using namespace std; #define MAXSIZE 12

洛谷P1282 多米诺骨牌

动态规划 题意: 对多米诺骨牌进行翻转,使其上下值最接近,求最小的翻转次数 1.状态 dp[ i ][ j ] 表示上面那排前i个数 和为 j 所需要的最小的翻转次数 2.状态转移方程 dp[ i ][ j ] = min(dp[ i ][ j ],dp[ i-1 ][ j-a[ i ] ] ) ; dp[ i ][ j ] = min(dp[ i ][ j ],dp[ i-1 ][ j-b[ i ] ]+1 ) ; 3.初始值 dp[ i ][ j ] = inf dp[ 0 ][ 0 ] =

多米诺骨牌题解

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

POJ 1135 Domino Effect(最短路 多米诺骨牌)

题意 题目描述: 你知道多米诺骨牌除了用来玩多米诺骨牌游戏外,还有其他用途吗?多米诺骨牌游戏:取一 些多米诺骨牌,竖着排成连续的一行,两张骨牌之间只有很短的空隙.如果排列得很好,当你推 倒第 1张骨牌,会使其他骨牌连续地倒下(这就是短语"多米诺效应"的由来). 然而当骨牌数量很少时,这种玩法就没多大意思了,所以一些人在 80 年代早期开创了另一个 极端的多米诺骨牌游戏:用上百万张不同颜色.不同材料的骨牌拼成一幅复杂的图案.他们开创 了一种流行的艺术.在这种骨牌游戏中,通常有多行骨牌同时

poj 1717==洛谷P1282 多米诺骨牌

Dominoes Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6571   Accepted: 2178 Description A domino is a flat, thumbsized tile, the face of which is divided into two squares, each left blank or bearing from one to six dots. There is a ro