标签:区间dp cst amp min pre string ++ class arp
题目大意:一系列村庄在一维坐标系上有序的排列,建设p个邮局,问各个村庄到邮局的最短距离和。
线性区间DP问题
dp数组的值为最短/最优距离
村庄和邮局为限制
dp[i][j]表示前i个村庄有j个邮局的最优解
分析最小子问题可得前i个村庄有1个邮局的最优解——中间的村庄
所以分解区间dp[i][j] = min(dp[i][j],dp[k][j-1] + sum[k+1][i])
sum[i][j]数组表示从i到j村庄放一个邮局的最优解
j,i,k的遍历,最终得到最优解
外层遍历的是邮局的个数,这样才能遍历村庄的个数(我们所未知的情况是村庄的个数大于邮局的个数)
对了sum【i】【j】和sum[i][j-1]存在某种关系呦,一推就出来了~~
#include <iostream> #include <cstdio> #include <string.h> #define inf (1e8 + 9e7) using namespace std; const int maxn = 1e3 + 1e2; int dp[maxn][maxn]; int sum[maxn][maxn]; int pos[maxn]; void init() { memset(sum,0,sizeof(sum)); } int main() { int n,pn; while(~scanf("%d%d",&n,&pn)) { init(); for(int i = 1;i <= n;i++) scanf("%d",&pos[i]); for(int i = 1;i <= n;i++) { for(int j = i+1;j <= n;j++) { sum[i][j] = sum[i][j-1] + pos[j] - pos[(i + j)/2]; } dp[i][i] = 0; } for(int i = 1;i <= n;i++) { dp[i][1] = sum[1][i]; } for(int j = 2;j <= pn;j++)//建造一个的情况已经铺垫好了 for(int i = j+1;i <= n;i++)//村庄首先必须保证得比 { //接下来我要做的是遍历k来找到到底几个村庄放j-1个最优 dp[i][j] = inf; for(int k = j - 1;k < i;k++) { dp[i][j] = min(dp[i][j],dp[k][j-1] + sum[k+1][i]); } } printf("%d\n",dp[n][pn]); } return 0; }
标签:区间dp cst amp min pre string ++ class arp
原文地址:https://www.cnblogs.com/DF-yimeng/p/9354117.html