HDU 6196 happy happy happy(暴搜+剪枝+dp)
2017-10-01 17:29
411 查看
来源:http://blog.csdn.net/snowy_smile/article/details/77929954
题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=6196
代码+思路:
题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=6196
代码+思路:
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<ctype.h> #include<math.h> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } #define MS(x, y) memset(x, y, sizeof(x)) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; } template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; } const int N = 100, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f; template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; } int casenum, casei; int n; int a ; int mn , mx ; int ST; int LIM = 0 * CLOCKS_PER_SEC; void init() { MS(mn, 63); MS(mx, -63); for (int i = 1; i <= n + 1; ++i) { mn[i][i - 1] = mx[i][i - 1] = 0; } for (int l = n; l >= 1; --l) { for (int r = l; r <= n; ++r) { int ll = l, rr = r; int sub; if (a[ll] >= a[rr])sub = a[ll++]; else sub = a[rr--]; gmax(mx[l][r], a[ll] + mx[ll + 1][rr] - sub); gmin(mn[l][r], a[ll] + mn[ll + 1][rr] - sub); gmax(mx[l][r], a[rr] + mx[ll][rr - 1] - sub); gmin(mn[l][r], a[rr] + mn[ll][rr - 1] - sub); } } } int ANS; void dfs(int l, int r, int dif) { if (l > r) { gmax(ANS, dif); return; } if (dif + mn[l][r] >= 0) return; //哪怕取一个最小值,都会赢了儿子,是个无效状态 if (dif + mx[l][r] <= ANS) return; //哪怕取一个最大值,差值都依然太小了,最优性剪枝 if (dif + mx[l][r] < 0) //取一个最大值,使得差值尽可能小,最优性剪枝 { gmax(ANS, dif + mx[l][r]); return; } int sub; if (a[l] >= a[r])sub = a[l++]; else sub = a[r--]; if (clock() - ST > LIM)return; //<1>取l,变成dfs(l + 1, r, dif + a[l]); dfs(l + 1, r, dif + a[l] - sub); //<2>取r,变成dfs(l, r - 1, dif + a[r]); dfs(l, r - 1, dif + a[r] - sub); } int main() { while(~scanf("%d", &n)) { for (int i = 1; i <= n; ++i)scanf("%d", &a[i]); init(); ST = clock(); ANS = -inf; dfs(1, n, 0); if (ANS == -inf) { puts("The child will be unhappy..."); } else { printf("%d\n", -ANS); } } return 0; } /* 【trick&&吐槽】 我的天,这数据水爆了啊,在0ms就可以AC了啊 【题意】 从1到n共计n(90)个物品,每个物品有一个价值a[] 小孩先手。小孩爸爸轮流做游戏。 爸爸每次可以取最左边或最右边的物品。 小孩每次选价值最大的{最左边,最右边}的物品,如果价值一样大, 则选取最左边的物品。 问你,爸爸想要输(价格严格小),而且差值尽可能少的最小差值是多少。 【分析】 首先,我们DP两个东西—— 1, mx[l][r]表示对于区间[l, r],儿子先手,爸爸所能拿到的最大价值差值(差值是爸爸减儿子) 2, mn[l][r]表示对于区间[l, r],儿子先手,爸爸所能拿到的最小价值差值(差值是爸爸减儿子) 那么—— 我们尝试使用搜索解决这个问题 dfs(l, r, dif)表示当前还没有取的区间范围是[l, r],儿子先手,此时爸爸减儿子的差值为dif。 那么—— 1,这时先考虑剪枝—— 设置初始ANS = -inf; void dfs(int l, int r, int dif) { if (dif + mn[l][r] >= 0) return; //哪怕取一个最小值,都会赢了儿子,是个无效状态 if (dif + mx[l][r] <= ANS) return; //哪怕取一个最大值,差值都依然太小了,最优性剪枝 if (dif + mx[l][r] < 0) //取一个最大值,使得差值尽可能小,最优性剪枝 { gmax(ANS, dif + mx[l][r]); } } 2,再模拟儿子的操作,获得新的(l, r, dif) 3,接着需要进一步地考虑爸爸的操作—— <1>取l,变成dfs(l + 1, r, dif + a[l]); <2>取r,变成dfs(l, r - 1, dif + a[r]); 4,考虑如何获得DP数组mn[][]和mx[][]—— mn[i][i - 1] = mx[i][i - 1] = 0; for(int l = n; l >= 1; --l) { for(int r = l; r <= n; ++r) { 先模拟儿子的操作,获得新的(ll, rr) 然后考虑父亲的操作—— 1,取ll: gmax(mx[l][r], a[ll] + mx[ll + 1][rr]); gmin(mn[l][r], a[ll] + mn[ll + 1][rr]); 2,取rr: gmax(mx[l][r], a[rr] + mx[ll][rr - 1]); gmin(mn[l][r], a[rr] + mn[ll][rr - 1]); } } 【时间复杂度&&优化】 O(0) */
相关文章推荐
- HDU 6196 happy happy happy 爆搜加剪枝
- HDU 6196 happy happy happy [折半暴搜+剪枝+DP]
- HDU 6196 happy happy happy(卡时剪枝)
- HDU 6196 happy happy happy (2017沈阳网赛 - 搜索 + dp + [黑科技。。。])
- hdu_2617 Happy 2009 (字符串)
- Happy Matt Friends HDU - 5119 (dp+滚动数组优化)
- HDU 1452 Happy 2004(因数之和)
- Happy 2004&&http://acm.hdu.edu.cn/showproblem.php?pid=1452
- HDU 6030 Happy Necklace[找规律][矩阵快速幂]
- HDU 5119 Happy Matt Friends
- hdu 5119 Happy Matt Friends【dp】
- HDU 4931 Happy Three Friends(水题)——BestCoder Round #4
- HDU 5119 Happy Matt Friends(递推+滚动数组)
- hdu 6030 Happy Necklace (递推,矩阵快速幂)
- HDU 5119 Happy Matt Friends(DP)
- HDU 4931 Happy Three Friends
- HDU 1452 Happy 2004(积性函数 逆元)
- hdu 5119 Happy Matt Friends 2014 北京区域赛 递推
- Hdu 6030 Happy Necklace【Dp+矩阵快速幂】
- hdu 1452 Happy 2004 因子和