J wyh的问题(区间dp)

链接:https://www.nowcoder.com/acm/contest/93/J
我国现在能源消耗非常严重,现在政府有这样一个工作,每天早上都需要把一些路灯关掉,但是他们想让在关闭的过程中所消耗的能源是最少的,负责路灯关闭的工作人员以1m/s的速度进行行走,假设关闭路灯的时候不需要花费任何的时间,请你编写一个程序,计算在给定路灯位置和每个路灯的消耗能源的多少,求出当所有路灯关闭的时候所需要的最少能量

显然可以得到一个结论,关闭[i, j]区间的电灯以后,关闭i-1或者j+1是下一步的最佳选择,所以可以通过区间dp来解决问题,dp[i][j][0/1]:已经关闭区间[i, j]的电灯,且站在左端点或者右端点的最小能源花费。然后每次关灯的路上的能源花费显然是[1, i-1]和[j+1, n]的电灯在费电。加个前缀和即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000 + 5;
const int INF = 0x3f3f3f3f;

int n, st;
int dist[maxn], w[maxn], pre[maxn];
int dp[maxn][maxn][2];


int dfs(int i, int j, int idx)
{
    if(i > j)   return 0;
    if(dp[i][j][idx] != INF)    return dp[i][j][idx];
    if(i == j)  return INF;

    int ret = INF;

    if(idx == 0)
    {
        ret = min(dfs(i+1,j,0) + (pre[n]-pre[j] + pre[i])*(dist[i+1]-dist[i]), dfs(i+1,j,1) + (pre[n]-pre[j] + pre[i])*(dist[j]-dist[i]));
    }
    else
    {
        ret = min(dfs(i,j-1,0) + (pre[n]-pre[j-1] + pre[i-1])*(dist[j]-dist[i]), dfs(i,j-1,1) + (pre[n]-pre[j-1] + pre[i-1])*(dist[j]-dist[j-1]));
    }
//    printf("[%d, %d, %d] = %d\n", i, j, idx, ret);
    return dp[i][j][idx] = ret;
}
int main()
{
    while(~scanf("%d%d", &n, &st))
    {
        for(int i = 1; i <= n; i++)    scanf("%d%d", &dist[i], &w[i]), pre[i] = pre[i-1] + w[i];
        memset(dp, INF, sizeof(dp));
        dp[st][st][0] = dp[st][st][1] = 0;
        printf("%d\n", min(dfs(1, n, 0), dfs(1, n, 1)));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_29556211/article/details/79929955
J
今日推荐