CF38ELet's Go Rolling! (dp)

Posted baseai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF38ELet's Go Rolling! (dp)相关的知识,希望对你有一定的参考价值。

前言

这题还是有点意思的。

题意: 给你 (n)(n<=3000)) 个弹珠,它们位于数轴上。给你弹珠的坐标 (x_i) 在弹珠 (i) 上面花费 (C_i) 的钱 可以使弹珠在原地不动 ((-10^9<=x_i,C_i<=10^9)),游戏开始时,所有的弹珠向左滚动,直到碰到定在原地不动的弹珠,其花费是其滚动的距离。总花费=开始前的花费+弹珠滚动的花费,问最小的花费是多少

题解

首先划分出阶段,,我们可以先将弹珠排序,前 (i) 个弹珠,最后一个固定的弹珠是 (j) ((j<i))

(=>)(f_{i,j}) 表示 前 (i) 个弹珠,最后一个固定的弹珠是 (j) ((j<i)) 的最小花费

可以这样想,当最后一个定点 (j)(i) 时,是不是就要在 (i) 的前面找到一个最小的定点继承 所以要找 (1<=k<i)(f_{i-1,k}) 最小的这个点,然后加上定 (i) 点的花费

而当最后一个定点 (j) 不在 (i) 时 只要在 (f_{i-1,j}) 的基础上加上点 (i) 到点 (j) 的距离

转移:

  • (f_{i,j}=min{f_{i-1,k}} + C_i (i==j))

  • (f_{i,j}=f_{i-1,j}+x_i-x_j (j<i))

Code

// int下INF=0x3f3f3f3f
// long long 下 INF=1e19 
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
#define int long long
#define INF 1e19
using namespace std;
inline int read() {
    int x=0,f=1; char ch=getchar();
    while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
    return x * f;
}
const int N = 3007;
int n;
int f[N][N];
struct Marbles {    //弹珠 
    int x,c;
}a[N];
bool cmp(Marbles x,Marbles y) {
    return x.x < y.x;
}
signed main()
{
    n = read();
    for(int i=1;i<=n;++i)
        a[i].x = read(), a[i].c = read();
    sort(a+1, a+1+n, cmp);
    int minn;
    f[1][1] = a[1].c;
    for(int i=2;i<=n;++i) {
        minn = INF;
        for(int j=1;j<i;++j) {
            f[i][j] = f[i-1][j] + a[i].x - a[j].x;
            minn = min(minn, f[i-1][j]);
        }
        f[i][i] = minn + a[i].c;
    }
    int ans = INF;
    for(int i=1;i<=n;++i)
        ans = min(ans, f[n][i]);
    cout<<ans<<endl;
    return 0;
}

以上是关于CF38ELet's Go Rolling! (dp)的主要内容,如果未能解决你的问题,请参考以下文章

「CF80A」Panoramix's Prediction

CF718EMatvey's Birthday BFS+动态规划

CF 1912 A NEKO's Maze Game

CF1279D Santa's Bot

Go36-38,39-bytes包

CF542DSuperhero's Job 暴力