P1220 关路灯

传送门

思路:

  很明显的区间动规。设 f [ i ][ j ][ k ] 表示从 i ~ j 的路灯全部关闭时,老张所处的位置[( k=0,处在 i 处),( k=1,处在 j 处)]。

△则可以得出转移方程式有:

    f [ i ][ j ][ 0 ] = min ( f [ i+1 ][ j ][ 0 ] + cal() , f [ i+1 ][ j ][ 1 ] + cal() );

    f [ i ][ j ][ 1 ] = min ( f[ i ][ j-1 ][ 0 ] + cal() , f[ i ][ j-1 ][ 1 ] + cal() );

注:cal() — 伪代码,计算从上一个区间转移过来时没关的路灯消耗的电力。

标程:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<string>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<queue>
#include<deque>
using namespace std;
#define maxn 60
#define INF 0x3f
int sum[maxn],a[maxn],b[maxn];//a记录位置,b记录功率 
int f[maxn][maxn][2];
int n,c;
inline int read()
{
    int kr=1,xs=0;
    char ls;
    ls=getchar();
    while(!isdigit(ls))
    {
        if(!(ls^45))
            kr=-1;
        ls=getchar();
    }
    while(isdigit(ls))
    {
        xs=(xs<<1)+(xs<<3)+(ls^48);
        ls=getchar();
    }
    return xs*kr;
}
int main()
{
    n=read();c=read();
    for(int i=1;i<=n;i++)
    {
        a[i]=read();b[i]=read();//读入这个灯的距离,功率 
        sum[i]=sum[i-1]+b[i];//可以利用前缀和快速查找到从 i ~ j 的功率和(下方动规转移要用) 
    }
    memset(f,INF,sizeof(f));
    f[c][c][0]=f[c][c][1]=0;//刚开始老张所处的点直接清零
    for(int l=2;l<=n;l++)//枚举区间长度
        for(int i=1;i+l-1<=n;i++)//枚举左端点 
        {
            int j=i+l-1;
            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]));//可以参考伪代码
        }
    printf("%d\n",min(f[1][n][0],f[1][n][1]));//输出 
return 0;
}

 

posted @ 2018-09-29 22:21  落笔映惆怅丶  阅读(173)  评论(0编辑  收藏  举报