BZOJ 1592 Usaco 2008 Feb Making the Grade 路面修整 DP

题目大意:给出一个不整齐的路面,可以将一个路面升高或者降低,都需要话费|x - x‘|的费用,把路面修正成单调不降或单调不升的最小花费是多少。

思路:路面的高度跨度有点大啊,先离散化。之后f[i][j] 表示到i为止路面保证单调不降并且最高高度为j的最小花费是多少,利用一个前缀和优化一下。单调不升也一样,简单DP水过。。

CODE:

#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 2010
#define INF 0x3f3f3f3f
using namespace std;

int cnt,src[MAX];
pair<int,int *> xx[MAX];
map<int,int> G;

int f[MAX][MAX],_f[MAX][MAX];//单调不降
int g[MAX][MAX],_g[MAX][MAX];//单调不升

int main()
{
    cin >> cnt;
    for(int i = 1; i <= cnt; ++i) {
        scanf("%d",&xx[i].first);
        xx[i].second = &src[i];
    }
    sort(xx + 1,xx + cnt + 1);
    int t = 0;
    for(int i = 1; i <= cnt; ++i) {
        if(i == 1 || xx[i].first != xx[i - 1].first)
            ++t;
        *xx[i].second = t;
        G[t] = xx[i].first;
    }
    memset(f,0x3f,sizeof(f));
    memset(g,0x3f,sizeof(g));
    for(int i = 1; i <= t; ++i)
        f[1][i] = g[1][i] = abs(G[src[1]] - G[i]);
    for(int i = 1; i <= cnt; ++i)
        _f[i][0] = _g[i][t + 1] = INF;
    for(int i = 1; i <= t; ++i)
        _f[1][i] = min(_f[1][i - 1],f[1][i]);
    for(int i = t; i; --i)
        _g[1][i] = min(_g[1][i + 1],g[1][i]);
    for(int i = 2; i <= cnt; ++i) {
        for(int j = 1; j <= cnt; ++j) {
            f[i][j] = _f[i - 1][j] + abs(G[j] - G[src[i]]);
            g[i][j] = _g[i - 1][j] + abs(G[j] - G[src[i]]);
        }
        for(int j = 1; j <= t; ++j)
            _f[i][j] = min(_f[i][j - 1],f[i][j]);
        for(int j = t; j; --j)
            _g[i][j] = min(_g[i][j + 1],g[i][j]);
    }
    int ans = INF;
    for(int i = 1; i <= t; ++i)
        ans = min(ans,min(f[cnt][i],g[cnt][i]));
    cout << ans << endl;
    return 0;
}

时间: 2024-10-22 06:02:44

BZOJ 1592 Usaco 2008 Feb Making the Grade 路面修整 DP的相关文章

【BZOJ 1592】[Usaco2008 Feb]Making the Grade 路面修整 dp优化之转移变状态

我们感性可证离散(不离散没法做),于是我们就有了状态转移的思路(我们只考虑单不减另一个同理),f[i][j]到了第i块高度为j的最小话费,于是我们就可以发现f[i][j]=Min(f[i-1][k])+|a[i]-j|(k<=j),于是我们的思路就去了各种数据结构--.然后我们发现对于这些转移就是在记录小于等于,那么我们直接带状态里体现这一点就可以了,而不是在转移的时候,我们f[i][j]表示到了第i个点小于等于j的高度的最小花费,这样我们就n^2了. #include <cstdio>

BZOJ 1592: [Usaco2008 Feb]Making the Grade 路面修整( dp )

最优的做法最后路面的高度一定是原来某一路面的高度. dp(x, t) = min{ dp(x - 1, k) } + | H[x] - h(t) | ( 1 <= k <= t ) 表示前 i 个路面单调不递减, 第 x 个路面修整为原来的第 t 高的高度. 时间复杂度O( n³ ). 令g(x, t) = min{ dp(x, k) } (1 <= k <= t), 则转移O(1), g() 只需在dp过程中O(1)递推即可, 总时间复杂度为O( n² ) 然后单调不递增也跑一遍

[BZOJ1592][Usaco2008 Feb]Making the Grade 路面修整

1592: [Usaco2008 Feb]Making the Grade 路面修整 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 735  Solved: 509 [Submit][Status][Discuss] Description FJ打算好好修一下农场中某条凹凸不平的土路.按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中. 整条路被分成了N段,N个整数A_1, ...

BZOJ 1592: [Usaco2008 Feb]Making the Grade 路面修整

Description FJ打算好好修一下农场中某条凹凸不平的土路.按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中. 整条路被分成了N段,N个整数A_1, ... , A_N (1 <= N <= 2,000)依次描述了每一段路的高度(0 <= A_i <= 1,000,000,000).FJ希望找到一个恰好含N个元素的不上升或不下降序列B_1, ... , B_N,作为修过的路中每个路段的高度.由于将每一段路垫高

【bzoj1592/Usaco2008 Feb】Making the Grade 路面修整——dp

Description FJ打算好好修一下农场中某条凹凸不平的土路.按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中. 整条路被分成了N段,N个整数A_1, ... , A_N (1 <= N <= 2,000)依次描述了每一段路的高度(0 <= A_i <= 1,000,000,000).FJ希望找到一个恰好含N个元素的不上升或不下降序列B_1, ... , B_N,作为修过的路中每个路段的高度.由于将每一段路垫高

【POJ3666】【USACO 2008 Feb Gold】 2.Cow Game 动规

题意:有若干个数,然后可以花费i的代价让某个数+i或者-i. 现在要求让你把序列排成不升或者不降,问最小代价. 题解: 首先可以证明,最优花费下最后所有的数都可以是现在的某个数: 证:如果两个数调整后在两个数中间,那么可以把两个数都变为其中一个数,而代价显然是等同的. 这个出来后就好做了. 我们可以先离散化一下,然后f[i][j]表示第i个数变为j时1~i这些数保持非严格单调的最小花费 转移时f[i][j]不必n*n枚举,可以维护一个前缀最优(非常水),然后O(1)转移. 然后做一遍非升,一遍非

BZOJ 1597 Usaco 2008 Mar 土地购买 斜率优化DP

题目大意:给出一些木板,现在要购买这些木板.购买的规则是可以一些木板一起买,然后价格是最大的长度乘最大的宽度.求购买所有木板的最小费用. 思路:如果一个木板的长也比一个木板小,宽也比一个木板小,那么这个木板就可以被排除.把所有木板按照x的长度排序,然后去掉排除的木板,然后剩下的木板就是x值下降, y值上升的木板.这样的话我们买下连续的一段的费用就是x[j] * y[i],然后DP方程就很简单了:f[i] = f[j] - x[j + 1] * y[i]. 注意到数据范围,写一个斜率优化就水过了.

BZOJ 1601 USACO 2008 Oct. 灌水

[Description] Farmer John已经决定把水灌到他的n(1<=n<=300)块农田,农田被数字1到n标记.把一块土地进行灌水有两种方法,从其他农田饮水,或者这块土地建造水库. 建造一个水库需要花费wi(1<=wi<=100000),连接两块土地需要花费Pij(1<=pij<=100000,pij=pji,pii=0). 计算Farmer John所需的最少代价. [题解] 新建一个节点0,把各个点与0点连边,边权为在该点上建水库的代价 然后跑一边最小生

BZOJ 1617 Usaco 2008 Mar. River Crossing渡河问题

[题解] 显然是个DP题. 设$f[i]$表示送$i$头牛过河所需的最短时间,预处理出$t[i]$表示一次性送i头牛过河所需时间,那么我们可以得到转移方程:$f[i]=min(f[i],f[i-j]+t[j]+t[0])$ (这里的$t[0]$指的是FJ独自过河的时间) 这样就可以做一个$n$方的DP了 #include<cstdio> #include<algorithm> #define rg register #define inf (1e9) #define N (1000