【洛谷P1880】合并石子
2017-04-29 21:28
246 查看
合并石子
Part 1:
链接:https://www.luogu.org/problem/show?pid=1880#sub
数据范围:1 < N <= 100
题解:朴素算法O(n^3)可过
DP[i][j]表示合并i到j的最小(大)代价
每堆石子可以看成先合并成两大堆石子,再把两大堆合并为一堆得到,合并的花费sum[i][j]
动态规划方程
![](https://img-blog.csdn.net/20170429211427908?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2RmemNoeQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
Part 2
这里引入四边形不等式优化
凸四边形不等式:w[a][c]+w[d]<=w[b][c]+w[a][d](a <= b < c < = d )
区间包含关系单调: w[b][c]<=w[a][d](a <=b < c <= d )
定理1: 如果w同时满足四边形不等式和决策单调性 ,则f也满足四边形不等式
定理2: 若f满足四边形不等式,则决策s满足 s[i][j-1]<=s[i][j]<=s[i+1][j]
定理3: w为凸当且仅当w[i][j]+w[i+1][j+1]<=w[i+1][j]+w[i][j+1]
证明:http://www.cnblogs.com/Mathics/p/3885745.html 或《动态规划算法的优化技巧》–毛子青
一般利用定理3证明凸函数,然后利用定理2的结论 s[i][j-1]<=s[i][j]<=s[i+1][j]
就能够使得复杂度由O(n^3)降低为O(n^2)
![](https://img-blog.csdn.net/20170429211930489?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2RmemNoeQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
这里可以应用于合并石子中求[b]最小值
Part 3
1 < N <= 2000 求合并后能得到的最大值
题解:
显然O(n^3)爆了
神奇地 f[i,j]=max(f[i+1][j],f[i][j-1])+w[i][j]
复杂度降到了O(n^2)
链接:http://cogs.pro/cogs/problem/problem.php?pid=1660
//如果有大佬路过,能说说为什么是这样吗,不太理解原理
Part 1:
链接:https://www.luogu.org/problem/show?pid=1880#sub
数据范围:1 < N <= 100
题解:朴素算法O(n^3)可过
DP[i][j]表示合并i到j的最小(大)代价
每堆石子可以看成先合并成两大堆石子,再把两大堆合并为一堆得到,合并的花费sum[i][j]
动态规划方程
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; #define is_num(tmp) (tmp<='9'&tmp>='0') #define maxn 0x3f3f3f3f int n,sum[250],dp[250][250]; inline int in(void) { char tmp(getchar()); int res(0),f(1); while(!(is_num(tmp)||tmp=='-'))tmp=getchar(); if(tmp=='-')f=-1,tmp=getchar(); while(is_num(tmp)) res=(res<<1)+(res<<3)+(tmp^48), tmp=getchar(); return res*f; } inline int DPmin() { for(int i=2;i<=n;i++) { for(int s=1;s<=2*n-i;s++) { int e= 4000 s+i-1; dp[s][e]=maxn; for(int k=s;k<e;k++) dp[s][e]=min(dp[s][e],dp[s][k]+dp[k+1][e]+sum[e]-sum[s-1]); } } int ans=maxn; for(int i=1;i<=n;i++) ans=min(ans,dp[i][i+n-1]); return ans; } inline int DPmax() { memset(dp,0,sizeof(dp)); for(int i=2;i<=n;i++) { for(int s=1;s<=2*n-i;s++) { int e=s+i-1; dp[s][e]=-maxn; for(int k=s;k<e;k++) dp[s][e]=max(dp[s][e],dp[s][k]+dp[k+1][e]+sum[e]-sum[s-1]); } } int ans=-maxn; for(int i=1;i<=n;i++) ans=max(ans,dp[i][i+n-1]); return ans; } int main() { int x; n=in(); for(int i=1;i<=n;i++) x=in(),sum[i]=sum[i+n]=sum[i-1]+x; for(int i=1;i<n;i++) sum[i+n]+=sum ; printf("%d\n%d\n",DPmin(),DPmax()); }
Part 2
这里引入四边形不等式优化
凸四边形不等式:w[a][c]+w[d]<=w[b][c]+w[a][d](a <= b < c < = d )
区间包含关系单调: w[b][c]<=w[a][d](a <=b < c <= d )
定理1: 如果w同时满足四边形不等式和决策单调性 ,则f也满足四边形不等式
定理2: 若f满足四边形不等式,则决策s满足 s[i][j-1]<=s[i][j]<=s[i+1][j]
定理3: w为凸当且仅当w[i][j]+w[i+1][j+1]<=w[i+1][j]+w[i][j+1]
证明:http://www.cnblogs.com/Mathics/p/3885745.html 或《动态规划算法的优化技巧》–毛子青
一般利用定理3证明凸函数,然后利用定理2的结论 s[i][j-1]<=s[i][j]<=s[i+1][j]
就能够使得复杂度由O(n^3)降低为O(n^2)
这里可以应用于合并石子中求[b]最小值
#include <cstdio> #include <cstring> #define N 1005 int s ,f ,sum ,n; int main() { while(scanf("%d",&n)!=EOF) { memset(f,127,sizeof(f)); sum[0]=0; for(int i=1; i<=n; i++){ scanf("%d",&sum[i]); sum[i]+=sum[i-1]; f[i][i]=0; s[i][i+1]=i; } for(int i=1; i<=n; i++) f[i][i+1]=sum[i+1]-sum[i-1]; for(int i=n-2; i>=1; i--) for(int j=i+2; j<=n; j++) for(int k=s[i][j-1]; k<=s[i+1][j]; k++) if(f[i][j]>f[i][k]+f[k+1][j]+sum[j]-sum[i-1]) { f[i][j]=f[i][k]+f[k+1][j]+sum[j]-sum[i-1]; s[i][j]=k; } printf("%d\n",f[1] ); } return 0; }
Part 3
1 < N <= 2000 求合并后能得到的最大值
题解:
显然O(n^3)爆了
神奇地 f[i,j]=max(f[i+1][j],f[i][j-1])+w[i][j]
复杂度降到了O(n^2)
链接:http://cogs.pro/cogs/problem/problem.php?pid=1660
//如果有大佬路过,能说说为什么是这样吗,不太理解原理
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define Maxm 999999997 using namespace std; int f[4010][4010],sum[4010]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&sum[i]),sum[i]+=sum[i-1]; for(int i=1;i<=n;i++) sum[i+n]=sum[i]+sum ; int ans=-Maxm; for(int i=2;i<=n;i++) for(int s=1;s<=2*n-i+1;s++) { int e=i+s-1; f[s][e]=max(f[s+1][e],f[s][e-1]); f[s][e]+=sum[e]-sum[s-1]; } for(int i=1;i<=n;i++) ans=max(ans,f[i][i+n-1]); printf("%d",ans); }
相关文章推荐
- 洛谷 p1880 石子合并 区间dp
- 洛谷 P1880 石子合并
- 洛谷 P1880 [NOI1995]石子合并
- 【洛谷】P1880 石子合并
- 【洛谷】P1880 石子合并
- DP 洛谷 P1880 [NOI1995]石子合并
- 洛谷 P1880 石子合并
- 洛谷P1880 石子合并
- 洛谷P1880 石子合并
- (ssl 1597 洛谷 1880)石子合并
- 洛谷P1080 石子合并
- [LUOGU] P1880 [NOI1995]石子合并
- 【学术篇】一石三鸟的——洛谷2654——原核生物培养(石子合并果子)
- 洛谷1880 石子合并
- P1880 [NOI1995]石子合并
- 【luogu】 P1880 石子合并
- 洛谷OJ - P1880 - 石子合并(区间DP)
- 洛谷1880 石子合并
- P1880 石子合并
- P1880 石子合并