POJ 1160 区间DP + 平行四边形优化
2017-08-28 09:14
441 查看
区间DP + 平行四边形优化
题意: 有n个村庄现在要建立m个邮局,问怎么建邮局才能使得村庄到最近的邮局距离和最小。输出距离和即可。
思路:
一般的区间dp是从小区间到大区间,而此题在此之外还有一个限制是m个邮局。对于此类问题可以直接建立dp的时候加上限制条件:dp[i][j]=min(dp[k][j−1]+one[k+1][i]) 定义dp含义为前i个村庄建立了j个邮局的最小距离和,那么在建立第j的时候可以枚举之前已经求出的区间,从j-1个邮局的前提下加上现在的1个邮局,one[i][j] 的含义是在区间i到j 的范围之中建立一个邮局,其实也就是中位数的位置,然后递推找出最小的值即可。
未优化代码。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 305; const int INF = 0x3f3f3f3f; int n,m; int a[maxn]; int one[maxn][maxn]; int dp[maxn][maxn]; int main() { //freopen("in.txt","r",stdin); scanf("%d%d",&n,&m); for(int i = 1;i <= n; i++) { scanf("%d",&a[i]); } for(int i = 1;i <= n; i++) { for(int j = i;j <= n; j++) { if(i == j) one[i][j] = 0; else one[i][j] = one[i][j-1] + a[j] - a[(i+j)/2]; } } memset(dp,INF,sizeof(dp)); for(int i = 1;i <= n; i++) dp[i][1] = one[1][i]; for(int i = 2;i <= n; i++) { int End = min(m,i); for(int j = 2;j <= End; j++) { for(int k = 1;k <= i; k++) { if(dp[i][j] > dp[k][j-1] + one[k+1][i]) dp[i][j] = dp[k][j-1] + one[k+1][i]; } } } printf("%d\n",dp [m]); return 0; }
可以用四边形优化
平行四边形的ss数组是优化的核心,但是它是建立在:m[i,j]=minm[i,k]+m[k,j](i≤k≤j) 条件下的。
而ss[i,j−1]≤ss[i,j]≤ss[i+1,j] 是最优解的优化,但是不知道ss[i+1][j] 如何算出,但是可以知道原本的上界i+1。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 305; const int INF = 0x3f3f3f3f; int n,m; int a[maxn]; int one[maxn][maxn]; int dp[maxn][maxn]; int ss[maxn][maxn]; int main() { //freopen("in.txt","r",stdin); scanf("%d%d",&n,&m); for(int i = 1;i <= n; i++) { scanf("%d",&a[i]); } for(int i = 1;i <= n; i++) { for(int j = i;j <= n; j++) { if(i == j) one[i][j] = 0; else one[i][j] = one[i][j-1] + a[j] - a[(i+j)/2]; } } memset(dp,INF,sizeof(dp)); memset(ss,0,sizeof(ss)); for(int i = 1;i <= n; i++) dp[i][1] = one[1][i]; for(int i = 2;i <= n; i++) { int End = min(m,i); for(int j = 2;j <= End; j++) { ss[i+1][j] = i+1; for(int k = ss[i][j-1];k <= ss[i+1][j]; k++) { if(dp[i][j] > dp[k][j-1] + one[k+1][i]) { dp[i][j] = dp[k][j-1] + one[k+1][i]; ss[i][j] = k; } } } } printf("%d\n",dp [m]); return 0; }
还有一个版本是i和j的循环可以换一换
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define inf 0x3f3f3f3f int dp[305][305]; int x[305],one[305][305]={0}; int K[305][305]; int main() { int N,M,i,j,k; // freopen("in.txt","r",stdin); while(cin>>N>>M){ for(i=1;i<=N;++i) scanf("%d",&x[i]); memset(dp,inf,sizeof(dp)); for(i=1;i<=N;++i) for(j=i;j<=N;++j) if(i==j) one[i][i]=0; else one[i][j]=one[i][j-1]+x[j]-x[(i+j)/2]; for(i=1;i<=N;++i) dp[i][1]=one[1][i]; for(i=1;i<=N;++i) K[i][i]=1; for(j=2;j<=M;++j) { for(i=1;i<=N;++i) { K[i+1][j]=i+1; if(j>i) continue; for(k=K[i][j-1];k<=K[i+1][j];++k) { int s=dp[k][j-1]+one[k+1][i]; if(dp[i][j]>s) { dp[i][j]=s; K[i][j]=k; } } } } printf("%d\n",dp [M]); } return 0; }
相关文章推荐
- POJ 1160 普通区间DP||四边形优化DP
- POJ 1160 经典区间dp/四边形优化
- POJ 1160 (区间DP+四边形优化)
- POJ 1160 Post Office 四边形不等式优化DP
- POJ-1160 Post office 四边形优化DP
- 四边形优化DP(POJ_1160 && HDU_2829 && HDU_3480 && HDU_3506 && HDU_3516)
- NYOJ 737 石子合并一(区间dp | 平行四边形优化)
- [DP 四边形不等式优化] POJ 1160 Post Office
- 【POJ1160】【四边形优化DP】Post Office
- poj 1160(四边形优化dp)
- dp四边形优化 poj 1160 Post Office题解
- HDU 3506 (环形石子合并)区间dp+四边形优化
- POJ 1160 Post Office (区间DP+重心)
- POJ 1160 Post Office (四边形不等式优化DP)
- POJ - 1160 Post Office(四边形优化)
- poj1160(区间DP)
- hdu3506 Monkey Party--区间dp & 石子归并 & dp四边形优化
- POJ 1160 Post Office(四边形不等式优化DP)
- POJ 1160 dp + 四边形优化
- poj 1160 Post Office(四边形不等式优化dp)