其他分享
首页 > 其他分享> > 【刷题】【dp】关路灯

【刷题】【dp】关路灯

作者:互联网

为了给村里节省电费,老张记录下了每盏路灯的位置和功率,他每次关灯时也都是尽快地去关,但是老张不知道怎样去关灯才能够最节省电。

他每天都是在天亮时首先关掉自己所处位置的路灯,然后可以向左也可以向右去关灯。

 

现在已知老张走的速度为1m/s,每个路灯的位置(是一个整数,即距路线起点的距离,单位:m)、功率(W),老张关灯所用的时间很短而可以忽略不计。

请你为老张编一程序来安排关灯的顺序,使从老张开始关灯时刻算起所有灯消耗电最少(灯关掉后便不再消耗电了)。

 

看下面:

将点与点之间的互相影响,拆开成每个点对其他的影响,

从而使方程转移无后效性

f[i][j][0] = min ( f[i+1][j][0] + ( a[i+1] - a[i] ) * ( sum[i] + sum[n] - sum[j] ) , f[i+1][j][1] + ( a[j]-a[i] ) * ( sum[i]+sum[n]-sum[j]) );

f[i][j][1] = min ( f[i][j-1][0] + ( a[j] - a[i] ) * ( sum[i-1] + sum[n] - sum[j-1] ) , f[i][j-1][1] + ( a[j]-a[j-1] ) * ( sum[i-1] + sum[n] - sum[j-1] ) );

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
int n,st;
const int N=53;
struct node
{
    int pos,p;
    bool operator < (const node & o) const
    { return pos<o.pos; }
}d[N];
int f[N][N][2],sum[N];

int main()
{
    scanf("%d%d",&n,&st);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&d[i].pos ,&d[i].p );
    for(int i=1;i<=n;i++)
        sum[i]=sum[i-1]+d[i].p ;
    
    memset(f,0x3f,sizeof(f));
    f[st][st][0]=f[st][st][1]=0;
    for(int i=1;i<n;i++)
        for(int j=max(st-i,1),k=j+i;j<=st && k<=n;j++,k++)
        {
            f[j][k][0]=min(f[j+1][k][0]+(d[j+1].pos -d[j].pos )*(sum[n]-sum[k]+sum[j]),
                         f[j+1][k][1]+(d[k].pos -d[j].pos )*(sum[n]-sum[k]+sum[j]) );
            f[j][k][1]=min(f[j][k-1][1]+(d[k].pos -d[k-1].pos )*(sum[n]-sum[k-1]+sum[j-1]),
                         f[j][k-1][0]+(d[k].pos -d[j].pos )*(sum[n]-sum[k-1]+sum[j-1]) );
        }
    printf("%d\n",min(f[1][n][0],f[1][n][1]));
    return 0;
}

 

标签:路灯,老张,const,sum,关灯,include,dp,刷题
来源: https://www.cnblogs.com/xwww666666/p/11716055.html