P1290-关灯

描述 Description
宁智贤得到了一份有趣而高薪的工作。每天早晨她必须关掉她所在村庄的街灯。所有的街灯都被设置在一条直路的同一侧。
宁智贤每晚到早晨5点钟都在晚会上,然后她开始关灯。开始时,她站在某一盏路灯的旁边。
每盏灯都有一个给定功率的电灯泡,因为宁智贤有着自觉的节能意识,她希望在耗能总数最少的情况下将所有的灯关掉。
宁智贤因为太累了,所以只能以1m/s的速度行走。关灯不需要花费额外的时间,因为当她通过时就能将灯关掉。
编写程序,计算在给定路灯设置,灯泡功率以及宁智贤的起始位置的情况下关掉所有的灯需耗费的最小能量。

输入格式 Input Format
第一行包含一个整数N,2≤N≤1000,表示该村庄路灯的数量。
第二行包含一个整数V,1≤V≤N,表示宁智贤开始关灯的路灯号码。
接下来的N行中,每行包含两个用空格隔开的整数D和W,用来描述每盏灯的参数,其中0≤D≤1000,0≤W≤1000。D表示该路灯与村庄开始处的距离(用米为单位来表示),W表示灯泡的功率,即在每秒种该灯泡所消耗的能量数。路灯是按顺序给定的。

输出格式 Output Format
第一行即唯一的一行应包含一个整数,即消耗能量之和的最小值。注意结果不超过1,000,000,000。


 

首先设出状态,f[i][j],f[i][j]代表把第i盏灯到第j栈灯全部关闭的最小消耗。
但是问题出现了,我们发现对于一个区间[i,j],我们从i走到j的消耗和从j走到i的消耗是不一样的,所以我们新开一维,f[i][j][1]代表从左走到右边,f[i][j][0]代表从右走到左边。
对于f[i][j],我们只能从左边或者右边递推而来,也就是从f[i][j−1]或者f[i+1][j]推来

注:p[i][j]表示关掉i-j之间的所有灯后其余灯消耗的功率和;

#include <bits/stdc++.h>
#include <BITS/STDC++.H>

using namespace std;

typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + 100;
const int MAXM = 3e3 + 10;

inline int read() {
    int x = 0, ff = 1; char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == '-') ff = -1;
        ch = getchar();
    }
    while(isdigit(ch)) {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * ff;
}

inline void write(int x) {
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

int n, v, p[MAXN], sum[MAXM][MAXM], f[MAXM][MAXM][3];
struct light {
    int dis, w;
}d[MAXN];

int main() {
    n = read(); v = read();
    for(int i = 1; i <= n; ++i) {
        d[i].dis = read();
        d[i].w = read();
    }
    for(int i = 1; i <= n; ++i)
        p[i] = p[i - 1] + d[i].w;
    for(int i = 1; i <= n; ++i) 
        for(int j = i; j <= n; ++j) 
            sum[i][j] = p[n] - (p[j] - p[i - 1]);
    memset(f, 0x3f, sizeof(f)); 
    f[v][v][0] = f[v][v][1] = 0; 
    for(int len = 2; len <= n; ++len) {
        for(int l = 1; l <= n - len + 1; ++l) {
            int r = l + len - 1;
            f[l][r][0] = min(f[l][r][0], f[l + 1][r][0] + (d[l + 1].dis - d[l].dis) * sum[l + 1][r]);
            f[l][r][0] = min(f[l][r][0], f[l + 1][r][1] + (d[r].dis - d[l].dis) * sum[l + 1][r]);
            f[l][r][1] = min(f[l][r][1], f[l][r - 1][0] + (d[r].dis - d[l].dis) * sum[l][r - 1]);
            f[l][r][1] = min(f[l][r][1], f[l][r - 1][1] + (d[r].dis - d[r - 1].dis) * sum[l][r - 1]);            
        }
    }
    write(min(f[1][n][0], f[1][n][1]));
    return 0;
}

 

posted @ 2019-04-10 12:59  海边微风起  阅读(321)  评论(0编辑  收藏  举报