• 「LuoguP1220」 关路灯(区间dp


    题目描述

    某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少)。老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯。

    为了给村里节省电费,老张记录下了每盏路灯的位置和功率,他每次关灯时也都是尽快地去关,但是老张不知道怎样去关灯才能够最节省电。他每天都是在天亮时首先关掉自己所处位置的路灯,然后可以向左也可以向右去关灯。开始他以为先算一下左边路灯的总功率再算一下右边路灯的总功率,然后选择先关掉功率大的一边,再回过头来关掉另一边的路灯,而事实并非如此,因为在关的过程中适当地调头有可能会更省一些。

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

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

    输入输出格式

    输入格式:

    文件第一行是两个数字n(1<=n<=50,表示路灯的总数)和c(1<=c<=n老张所处位置的路灯号);

    接下来n行,每行两个数据,表示第1盏到第n盏路灯的位置和功率。数据保证路灯位置单调递增。

    输出格式:

    一个数据,即最少的功耗(单位:J,1J=1W·s)。

    输入输出样例

    输入样例#1: 复制
    5 3
    2 10
    3 20
    5 20
    6 30
    8 10
    输出样例#1: 复制
    270  

    说明

    输出解释:

    {此时关灯顺序为3 4 2 1 5,不必输出这个关灯顺序}


    题解

    吐槽:这是一道会生崽的题所以肥肠重要QAQ(大概也就考过个三四次改编题了吧

    就是比较基础的区间dp啦

    设F[L][R][0]为区间[L,R]的灯都关掉,并且站在区间左端时已经消耗的功率最小值,

    同理,F[L][R][1]为区间[L,R]的灯都关掉,并且站在区间右端是已消耗功率的最小值。

    转移方程:

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

    最后的答案是F[1][n][0]和F[1][n][1]中的较小值。

     1 /*
     2     qwerta
     3     P1220 关路灯
     4     Accepted
     5     100
     6     代码 C++,0.87KB
     7     提交时间 2018-07-04 17:04:07
     8     耗时/内存
     9     0ms, 2195KB
    10 */
    11 #include<cmath>
    12 #include<cstdio>
    13 #include<cstring>
    14 #include<iostream>
    15 #include<algorithm>
    16 using namespace std;
    17 int a[57];
    18 int n,c;
    19 int sum[57];
    20 void scan()
    21 {
    22     scanf("%d%d",&n,&c);
    23     int u;
    24     for(int i=1;i<=n;++i)
    25     {
    26         scanf("%d%d",&a[i],&u);
    27         sum[i]=sum[i-1]+u;
    28     }
    29     return;
    30 }
    31 int f[57][57][2];
    32 void run()
    33 {
    34     memset(f,127,sizeof(f));
    35     f[c][c][0]=f[c][c][1]=0;
    36     for(int l=1;l<n;++l)
    37     for(int i=1;i+l<=n;++i)
    38     {
    39         int j=i+l;
    40         f[i][j][0]=min(f[i+1][j][0]+(a[i+1]-a[i])*(sum[n]+(sum[i]-sum[j])),
    41                        f[i+1][j][1]+(a[j]-a[i])*(sum[n]+(sum[i]-sum[j])));
    42         f[i][j][1]=min(f[i][j-1][0]+(a[j]-a[i])*(sum[n]+(sum[i-1]-sum[j-1])),
    43                        f[i][j-1][1]+(a[j]-a[j-1])*(sum[n]+(sum[i-1]-sum[j-1])));
    44     }
    45     return;
    46 }
    47 int main()
    48 {
    49     scan();
    50     run();
    51     cout<<min(f[1][n][0],f[1][n][1]);
    52     return 0;
    53     //我当年的码风真丑
    54 }
  • 相关阅读:
    ubuntu:activate root
    C/C++ char* arr与char arr[]的区别(反汇编解析)
    [转]关于编写Nios II的延时函数的一点心得
    [转]Xilinx Vivado的使用详细介绍(1):创建工程、编写代码、行为仿真、Testbench
    [转]Vivado中IP的使用方法
    [转]Vivado IP核生成设置
    [转]VHDL中数据类型转换与移位(STD_LOGIC_ARITH与NUMERIC_STD)
    [转]Vivado与SDK的联合调试方法-使用ILA
    [转]Vivado中ILA的使用
    [转]vivado硬件调试——mark_debug
  • 原文地址:https://www.cnblogs.com/qwerta/p/9690883.html
Copyright © 2020-2023  润新知