nyoj 325 zb的生日【01背包||dfs】

xiaoxiao2021-02-28  92

zb的生日

时间限制: 3000 ms  |  内存限制: 65535 KB 难度: 2 描述 今天是阴历七月初五,acm队员zb的生日。zb正在和C小加、never在武汉集训。他想给这两位兄弟买点什么庆祝生日,经过调查,zb发现C小加和never都很喜欢吃西瓜,而且一吃就是一堆的那种,zb立刻下定决心买了一堆西瓜。当他准备把西瓜送给C小加和never的时候,遇到了一个难题,never和C小加不在一块住,只能把西瓜分成两堆给他们,为了对每个人都公平,他想让两堆的重量之差最小。每个西瓜的重量已知,你能帮帮他么? 输入 多组测试数据(<=1500)。数据以EOF结尾 第一行输入西瓜数量N (1 ≤ N ≤ 20) 第二行有N个数,W1, …, Wn (1 ≤ Wi ≤ 10000)分别代表每个西瓜的重量 输出 输出分成两堆后的质量差 样例输入 5 5 8 13 27 14 样例输出 3 来源

ural

思路:

一直TLE,看了宇神博客惊奇的发现,宏定义的max函数给AC了;本题是把两堆西瓜平均分使差值最小,有意思的是这个题的价值和重量是一个概念(相对于普通的01背包),之后就可已01背包解决了;

#include <cstdio> #include <cstring> #define max(a, b) (a > b? a: b) //真要写成这样才给过,自己写的函数快 int dp[100010], a[30]; int main() { int n; while(scanf("%d", &n) != EOF) { int sum = 0; memset(dp, 0, sizeof(dp)); for(int i = 0; i < n; i++) { scanf("%d", &a[i]); sum += a[i]; } int v = sum; sum >>= 1; for(int i = 0; i < n; i++) { for(int j = sum; j >= a[i]; j--) { dp[j] = max(dp[j], dp[j - a[i]] + a[i]); } } printf("%d\n", v - dp[sum]*2); } return 0; } 思路:

加一个剪枝就过了,n比较小,dfs应该才是正解,毕竟估计一下复杂度,1500*10000*20,;

#include <cstdio> #include <cstring> #define max(a, b) (a > b? a: b) int dp[100010], a[30]; int n, sum = 0, v, maxn; void dfs(int x, int val) { if(val > sum) return; if( x == n) { maxn = max(val, maxn); return; } dfs(x + 1, val + a[x + 1]); dfs(x + 1, val); return ; } int main() { while(scanf("%d", &n) != EOF) { maxn = 0; sum = 0; memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); sum += a[i]; } v = sum; sum >>= 1; dfs(0, 0); printf("%d\n", v - maxn*2); } return 0; }

转载请注明原文地址: https://www.6miu.com/read-38008.html

最新回复(0)