决策单调性Ⅰ:四边形不等式(bzoj 1563: [NOI2009]诗人小G)
2017-10-08 14:13
405 查看
题目描述:
给出n个数字和常数L,你可以任意合并相邻的两个数字a[x]和a[x+1],并得出一个新的数a[x]+a[x+1]+1,一通合并后得到一个有若干个数的序列,这个序列的不协调值为∑|(a[i]-L)^p|,求最小不协调值
例如L=7,初始4个数分别为3 3 1 5,那么肯定是将前两个数合并,后两个数合并得出7 7,这时不协调值一定为0
n<=100000,L<=300000,P<=10
设dp[i]为前i个数的最小不协调度,len[]为第i个数有
复杂度O(n²P),肯定过不去
当P=2时,设sum[]为len[]的前缀和,若k点比j点更优,且j<k<i,那么有
维护一个下凸包,这样当P=2时,斜率优化复杂度O(n)
斜率优化可见:决策单调性Ⅱ:斜率优化
这就是题目
1010: [HNOI2008]玩具装箱toy 的题解
可这题P不一定等于2,还是过不去
不过以上说明了这个DP可能是有决策单调性的
那么先说:什么是决策单调性?
先提一个词:1D/1D动态规划,指的是状态为O(n),每一个状态决策都需要O(n)遍历前面所有决策才能得出的动态规划,直接求解的复杂度是O(n²),但很多情况下都可以通过一系列手段优化成O(nlogn)或者O(n)(例如平行四边形优化 和斜率优化)
1D/1D动态规划经典模型:
假设j点是当前i点的最优决策,那么决策单调性就是指:
对于所有的x>i,最优决策p(x)一定都大于j
也可这么理解:假设a是dp[x]的最优决策,b是dp[x-1]点的最优决策,a>b,那么对于所有的p>x,从a点转移一定比b点更优,对于所有的p<x-1,从b点转移一定比a点更优
还可以这么理解:每个决策点能决策的区间一定是连续的一段,并且随着决策点的右移,这个区间也在不断右移
充要条件:
具体证明比较复杂,而且题目不同证明应该也会有不同,这里就略
贴一篇证明https://www.byvoid.com/zhs/blog/noi-2009-poet
一般题目都能看出来,没必要证,等你证完别人都AC了
那么知道了决策单调性,怎么搞?
通过上面蓝色字体,可以这样思考:对于当前决策点,它能影响的区间是哪些?
举个例子假设n=30,一步一步来:
先搞出dp[1],那么所有后续状态dp[x]的目前最优决策一定都是1,决策表如下:
111111111111111111111111111111
然后再算出dp[2],由于决策单调性,决策表一定会变成这样:
111111111122222222222222222
再算出dp[3]:111111111122222233333333333
再算出dp[4]:111111111122222244444444444
再算出dp[5]:111111111122222244555555555
……
那么可以看出,每个决策在决策表中一定会有且只有一个转折点
理论上只要知道这个转折点就可以
具体过程:
用一个栈来维护,里面保存每一个决策的起始位置和终点位置,显然这些位置是首尾相接的
每出现一个新决策,从后往前扫描栈,这个时候有两种情况:
①如果在某个老决策起点处新决策更好,那么把这个老决策直接弹出栈(扔掉),用新决策代替之,就如同上面例子中算出dp[4]之后,决策3被完全抛弃
②如果在某个老决策起点处还是老决策更好,那么转折点必定在这个老决策区间内,二分查找并插入新决策
复杂度分析:每个决策出栈进栈1次,每次二分,所以O(nlogn)
回到这题,看DP式子
这不就是
的模型题么,其中w[i, j]就是后面那一长串
就用上述方法就ok了
Submit: 2736 Solved: 885
[Submit][Status][Discuss]
4 9 3
brysj,
hhrhl.
yqqlm,
gsycl.
4 9 2
brysj,
hhrhl.
yqqlm,
gsycl.
1 1005 6
poet
1 1004 6
poet
--------------------
32
--------------------
Too hard to arrange
--------------------
1000000000000000000
--------------------
这题就是上面那个例子,代码里有注释
给出n个数字和常数L,你可以任意合并相邻的两个数字a[x]和a[x+1],并得出一个新的数a[x]+a[x+1]+1,一通合并后得到一个有若干个数的序列,这个序列的不协调值为∑|(a[i]-L)^p|,求最小不协调值
例如L=7,初始4个数分别为3 3 1 5,那么肯定是将前两个数合并,后两个数合并得出7 7,这时不协调值一定为0
n<=100000,L<=300000,P<=10
设dp[i]为前i个数的最小不协调度,len[]为第i个数有
复杂度O(n²P),肯定过不去
当P=2时,设sum[]为len[]的前缀和,若k点比j点更优,且j<k<i,那么有
维护一个下凸包,这样当P=2时,斜率优化复杂度O(n)
斜率优化可见:决策单调性Ⅱ:斜率优化
这就是题目
1010: [HNOI2008]玩具装箱toy 的题解
可这题P不一定等于2,还是过不去
不过以上说明了这个DP可能是有决策单调性的
那么先说:什么是决策单调性?
先提一个词:1D/1D动态规划,指的是状态为O(n),每一个状态决策都需要O(n)遍历前面所有决策才能得出的动态规划,直接求解的复杂度是O(n²),但很多情况下都可以通过一系列手段优化成O(nlogn)或者O(n)(例如平行四边形优化 和斜率优化)
1D/1D动态规划经典模型:
假设j点是当前i点的最优决策,那么决策单调性就是指:
对于所有的x>i,最优决策p(x)一定都大于j
也可这么理解:假设a是dp[x]的最优决策,b是dp[x-1]点的最优决策,a>b,那么对于所有的p>x,从a点转移一定比b点更优,对于所有的p<x-1,从b点转移一定比a点更优
还可以这么理解:每个决策点能决策的区间一定是连续的一段,并且随着决策点的右移,这个区间也在不断右移
充要条件:
具体证明比较复杂,而且题目不同证明应该也会有不同,这里就略
贴一篇证明https://www.byvoid.com/zhs/blog/noi-2009-poet
一般题目都能看出来,没必要证,等你证完别人都AC了
那么知道了决策单调性,怎么搞?
通过上面蓝色字体,可以这样思考:对于当前决策点,它能影响的区间是哪些?
举个例子假设n=30,一步一步来:
先搞出dp[1],那么所有后续状态dp[x]的目前最优决策一定都是1,决策表如下:
111111111111111111111111111111
然后再算出dp[2],由于决策单调性,决策表一定会变成这样:
111111111122222222222222222
再算出dp[3]:111111111122222233333333333
再算出dp[4]:111111111122222244444444444
再算出dp[5]:111111111122222244555555555
……
那么可以看出,每个决策在决策表中一定会有且只有一个转折点
理论上只要知道这个转折点就可以
具体过程:
用一个栈来维护,里面保存每一个决策的起始位置和终点位置,显然这些位置是首尾相接的
每出现一个新决策,从后往前扫描栈,这个时候有两种情况:
①如果在某个老决策起点处新决策更好,那么把这个老决策直接弹出栈(扔掉),用新决策代替之,就如同上面例子中算出dp[4]之后,决策3被完全抛弃
②如果在某个老决策起点处还是老决策更好,那么转折点必定在这个老决策区间内,二分查找并插入新决策
复杂度分析:每个决策出栈进栈1次,每次二分,所以O(nlogn)
回到这题,看DP式子
这不就是
的模型题么,其中w[i, j]就是后面那一长串
就用上述方法就ok了
1563: [NOI2009]诗人小G
Time Limit: 100 Sec Memory Limit: 64 MBSubmit: 2736 Solved: 885
[Submit][Status][Discuss]
Description
Input
Output
对于每组数据,若最小的不协调度不超过1018,则第一行一个数表示不协调度若最小的不协调度超过1018,则输出"Too hard to arrange"(不包含引号)。每个输出后面加"--------------------"Sample Input
44 9 3
brysj,
hhrhl.
yqqlm,
gsycl.
4 9 2
brysj,
hhrhl.
yqqlm,
gsycl.
1 1005 6
poet
1 1004 6
poet
Sample Output
108--------------------
32
--------------------
Too hard to arrange
--------------------
1000000000000000000
--------------------
这题就是上面那个例子,代码里有注释
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define LL long long #define Inf 1e18 #define LD long double int n, L, p, top, st[100005], k[100005], a[100005], sum[100005]; LD dp[100005]; LD Pow(int x, int y) { int i; LD ans = 1; for(i=1;i<=y;i++) ans = ans*x; if(ans<0) ans = -ans; return ans; } LD Calc(int j, int i) { return dp[j]+Pow(sum[i]-sum[j]+i-j-1-L, p); } int Find(int x) { int l, r, m; l = 1, r = top; while(l<r) { m = (l+r+1)/2; if(x>=k[st[m]]) l = m; else r = m-1; } return r; } int Find_pos(int i, int x) { int l, r, m; l = max(i+1, k[x]+1), r = n+1; while(l<r) { m = (l+r)/2; if(Calc(i, m)<Calc(x, m)) r = m; else l = m+1; } return r; } int main(void) { char str[35]; int i, T, x; scanf("%d", &T); while(T--) { scanf("%d%d%d", &n, &L, &p); for(i=1;i<=n;i++) { scanf("%s", str+1); a[i] = strlen(str+1); sum[i] = sum[i-1]+a[i]; } top = 0, k[0] = 0; st[++top] = 0; for(i=1;i<=n;i++) { x = st[Find(i)]; //找到i点所在区间是哪个最优决策点的区间 dp[i] = Calc(x, i); //因为是最优决策点,直接计算 while(k[st[top]]>i && Calc(i, k[st[top]])<Calc(st[top], k[st[top]])) //对于当前新决策,从后往前扫描栈 top--; //如果在某个老决策起点处新决策更好,那么直接把这个老决策直接弹出栈(扔掉),用新决策代替之 x = Find_pos(i, st[top]); //如果在某个老决策起点处还是老决策更好,那么转折点必定在这个老决策区间内,二分查找并插入新决策 if(x==n+1) //↑↑这里偷个懒,直接扫老决策起点往后的整个数组而不是扫老决策区间 continue; k[i] = x; st[++top] = i; //插入新决策 } /*for(i=1;i<=n;i++) { dp[i] = 7*Inf; for(j=0;j<=i-1;j++) dp[i] = min(dp[i], Calc(j, i)); }*/ if(dp >Inf) printf("Too hard to arrange\n--------------------\n"); else printf("%lld\n--------------------\n", (LL)dp ); } return 0; } /* 1 4 9 2 brysj, hhrhl. yqqlm, gsycl. */
相关文章推荐
- bzoj1563: [NOI2009]诗人小G【决策单调性优化dp】
- BZOJ 1563: [NOI2009]诗人小G 决策单调性DP
- 【NOI2009】bzoj1563 诗人小G
- [BZOJ1563][NOI2009]诗人小G(决策单调性优化DP)
- BZOJ_1563_[NOI2009]诗人小G_决策单调性
- bzoj 1563: [NOI2009]诗人小G
- [bzoj1563][NOI2009]诗人小G(决策单调性优化)
- bzoj1563: [NOI2009]诗人小G
- [BZOJ 1563][NOI 2009]诗人小G(四边形优化DP)
- 【决策单调性的动态规划】noi2009诗人小G
- 【BZOJ1563】【NOI2009】诗人小G(dp+决策单调性)
- [BZOJ1563][NOI2009]诗人小G(dp+决策单调性)
- BZOJ 1563 NOI2009 诗人小G 四边形不等式
- 【BZOJ 1563】 (四边形优化、决策单调性)
- 1563: [NOI2009]诗人小G
- 1563: [NOI2009]诗人小G
- bzoj 1563 [NOI2009]诗人小G 四边形不等式 决策单调dp
- bzoj1563 [NOI2009]诗人小G
- BZOJ 1562 [NOI2009]变换序列 (二分图匹配)
- BZOJ1565 [NOI2009]植物大战僵尸(拓扑排序 + 最大权闭合子图)