区间dp——POJ - 1160

题目含义

v个村庄要建p个邮局

现给出每个村庄的位置,并且邮局只能建在村庄的位置

问每个村庄到离它最近的邮局距离之和最小为多少

题目分析

区间dp[i][j]表示在前i个村庄建j个邮局的最小距离

dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][j])

这个状态方程表示,将【在前i个村庄建j个邮局的距离】划分成【在前k个村庄建j-1个邮局的距离】加上【在第k+1个村庄到第j个村庄之间建一个邮局的距离】

题目代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
int v,p;
int a[307],dis[307][307],dp[307][307];
int main(){
    scanf("%d%d",&v,&p);
    for(int i=1;i<=v;i++){
        scanf("%d",&a[i]);
    }
    memset(dis,0,sizeof(dis));
    for(int i=1;i<=v;i++)
    for(int j=i+1;j<=v;j++){
        dis[i][j]=dis[i][j-1]+a[j]-a[(i+j)/2];
    }
    memset(dp,INF,sizeof(dp));
    for(int i=1;i<=v;i++){
        dp[i][i]=0;
        dp[i][1]=dis[1][i];
    }
    for(int j=2;j<=p;j++)
    for(int i=j+1;i<=v;i++){
        for(int k=j-1;k<i;k++)
            dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][i]);
    }
    printf("%d\n",dp[v][p]);
    return 0;
}

原文地址:https://www.cnblogs.com/helman/p/11246720.html

时间: 2024-10-19 16:58:32

区间dp——POJ - 1160的相关文章

区间DP [POJ 1141] Brackets Sequence

Brackets Sequence Description Let us define a regular brackets sequence in the following way: 1. Empty sequence is a regular sequence. 2. If S is a regular sequence, then (S) and [S] are both regular sequences. 3. If A and B are regular sequences, th

[区间dp] poj 3280 Cheapest Palindrome

题意: 给出增加或减少某个字符的代价. 给你一个串,求让它变成回文串的最小代价. 思路: 和求次数一样. 然后注意的是其实增加和减少的性质是一样的.所以对于每个字符,取修改代价最小的就行了. 意思就是取增加和减少的最小值. 其他就同求次数的区间dp了. 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"q

POJ 1160 (区间DP+四边形优化)

这个转移方程不好想,尤其是一段值的解是中间,不明觉厉.dp[i][j] 用i个邮局,覆盖前j个村庄的最小值. 还有就是区间dp的平行四边形优化,这个题的转移方程并不是"区间DP",所以枚举状态要逆着(很花时间),且用一个邮局覆盖都是从0断开了相当于没有断开. 类比于石子归并,矩阵链乘等标准区间DP,其所需状态之前就已经获得,不用倒推 #include <cstdio> #include <cstring> #include <iostream> us

POJ 2955:Brackets(区间DP)

http://poj.org/problem?id=2955 题意:给出一串字符,求括号匹配的数最多是多少. 思路:区间DP. 对于每个枚举的区间边界,如果两边可以配对成括号,那么dp[i][j] = dp[i+1][j-1] + 2,表示由上一个状态加上当前的贡献. 然后和普通的区间合并一样去更新. 1 #include <cstring> 2 #include <cstdio> 3 #include <iostream> 4 #include <string&

uva1626 poj 1141 Brackets Sequence 区间dp 打印路径

// poj 1141 Brackets Sequence // 也是在紫书上看的一题,uva就是多了一个t组数据. // 经典区间dp // dp(i,j)表示区间[i,j]内所需要增加的括号数目 // 则分为两种情况 // 一种是s[i]和s[j]是匹配的则 // dp[i][j] = min(dp[i][j],dp[i+1][j-1]) // 另外一种情况是不匹配 // dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]){i<k<j}; // 但是无

POJ 3042 Grazing on the Run (区间DP)

区间dp,~~~~ dp[i][j][0]表示i到j之间已经走过,并且现在在i点的staleness(可以理解为枯萎指数)最小值, dp[i][j][1]表示i到j之间已经走过,并且现在在j点的staleness最小值. 于是对于在i点,可能从i+1->i,也可能从j->i,即: 很重要的一点,在我们转移到i时,除了即将到达的i点,还有未到达的(n-(j-i+1))个点,即总共(n-(j-i))个点,它们的枯萎指数均在增加,so~ dp[i][j][0]=min(dp[i+1][j][0]+(

POJ 1651 Multiplication Puzzle (区间dp)

题目大意:对n个数组成的序列取数,规定最两边不能取,每次取一个a[i],得到 a[l] * a[i] * a[r] 的分数(a[l]是a[i]左边的数,a[r]是a[i]右边的数),并把这个数从序列中移走,求n-2次取数后的得分和的最小值 分析:正着确定状态不好做,不如反着来,设dp[l][r]为向区间[l, r]中填满数所得到分数和的最小值,考虑最近一次填数的位置,不难得出: dp[l][r] = fmin(dp[l][m] + dp[m][r] + a[l] * a[m] * a[r]) (

POJ 1179 Polygon 区间DP

链接:http://poj.org/problem?id=1179 题意:给出一个多边形,多边形的每个顶点是一个数字,每条边是一个运算符号"+"或者"x".要求的过程如下,手下移除一条边,即这条边不做运算.之后每次移除一条边,将其两边的数字进行对应边的运算,用得到的数字来替代原来的两个点.要求所有边都移除以后得到的最大的答案. 思路:典型的区间DP,在过程中每次操作的处理方式为dp_max[i][j]=dp[i][k]*dp[k+1][j],dp_max[i][j]

POJ 3186Treats for the Cows(区间DP)

题目链接:http://poj.org/problem?id=3186 题目大意:给出的一系列的数字,可以看成一个双向队列,每次只能从队首或者队尾出队,第n个出队就拿这个数乘以n,最后将和加起来,求最大和. 解题思路:有两种写法: ①这是我一开始想的,从外推到内,设立数组dp[i][j]表示剩下i~j时的最优解,则有状态转移方程: dp[i][j]=dp[i][j]=max(dp[i-1][j]+a[i-1]*(n-(j-i+1)),dp[i][j+1]+a[j+1]*(n-(j+1-i)))