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]+(n-(j-i))*(pos[i+1]-pos[i]),dp[i+1][j][1]+(n-(j-i))*(pos[j]-pos[i]));

同理对于当前在j点,也可以得到向相应的方程:

dp[i][j][1]=min(dp[i][j-1][1]+(n-(j-i))*(pos[j]-pos[j-1),dp[i][j-1][0]+(n-(j-i))*(pos[j]-pos[i])).

最后需要注意的就是初始话的问题了,找到L在原序列中的位置就好。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

题目链接:http://poj.org/problem?id=3042

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1000+10
using namespace std;

int p[N];
int f[N][N][2];
int main()
{
    int n,s;
    while(~scanf("%d%d",&n,&s))
    {
        int ok=1;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&p[i]);
            if(p[i]==s) ok=0; //可能存在某点与起点重合的情况。
        }
        if(ok) p[n++]=s;
        sort(p,p+n);
        int pos=lower_bound(p,p+n,s)-p; //二分查找L的位置。
        memset(f,0x3f,sizeof(f));
        f[pos][pos][0]=f[pos][pos][1]=0; //起点~
        for(int i=pos;i>=0;i--)
        {
            for(int j=pos;j<n;j++)
            {
                f[i][j][0]=min(f[i][j][0],f[i+1][j][0]+(n-(j-i))*(p[i+1]-p[i]));
                f[i][j][0]=min(f[i][j][0],f[i+1][j][1]+(n-(j-i))*(p[j]-p[i]));
                f[i][j][1]=min(f[i][j][1],f[i][j-1][1]+(n-(j-i))*(p[j]-p[j-1]));
                f[i][j][1]=min(f[i][j][1],f[i][j-1][0]+(n-(j-i))*(p[j]-p[i]));
            }
        }
        printf("%d\n",min(f[0][n-1][0],f[0][n-1][1]));
    }
    return 0;
}

POJ 3042 Grazing on the Run (区间DP)

时间: 2024-08-06 03:44:14

POJ 3042 Grazing on the Run (区间DP)的相关文章

POJ 1991 Turning in Homework(区间DP)

题目链接 Turning in Homework 考虑区间DP f[i][j][0]为只考虑区间[i, j]且最后在a[i]位置交作业的答案. f[i][j][1]为只考虑区间[i, j]且最后在a[j]位置交作业的答案. 首先对a[i]升序排序(位置第一关键字,时间第二关键字) 然后就是区间DP了 f[i][j]可以从f[i][j + 1], f[i - 1][j]推过来. 即 f[i][j][0] = min(f[i][j][0], max(f[i][j + 1][1] + a[j + 1]

POJ 题目1141 Brackets Sequence(区间DP记录路径)

Brackets Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 27793   Accepted: 7885   Special Judge Description Let us define a regular brackets sequence in the following way: 1. Empty sequence is a regular sequence. 2. If S is a re

【POJ】3280 Cheapest Palindrome(区间dp)

Cheapest Palindrome Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10943   Accepted: 5232 Description Keeping track of all the cows can be a tricky task so Farmer John has installed a system to automate it. He has installed on each cow

poj 3186 Treats for the Cows (区间dp)

题意:给你一个序列,每次只能从头或为取数,然后乘以这是第几个数,最后加和,是加和最大 思路:假设长度最开始是1,然后依次枚举长度,以及起点,dp[i][j]是又里面的两端点扩出来的(ps:代码不是这么写的) 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=2007; int a[maxn],dp[maxn][maxn]; i

bzoj 1742: [Usaco2005 nov]Grazing on the Run 边跑边吃草【区间dp】

挺好的区间dp,状态设计很好玩 一开始按套路设f[i][j],g[i][j]为吃完(i,j)区间站在i/j的最小腐败值,后来发现这样并不能保证最优 实际上是设f[i][j],g[i][j]为从i开始吃j个,站在这段区间的左/右端点的 * 最小所有草增加的腐败值 * ,因为这些腐败之最后也是要算进去的,所以直接夹在里面就可以保证最优 #include<iostream> #include<cstdio> #include<cstring> #include<algo

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 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]