• 洛谷 P1220 关路灯(区间dp,前缀和)


    传送门


    解题思路

    先明确一下题意,c指的是路灯的编号而不是位置。

    然后根据贪心,在从点i去关点j的路灯时,所有经过的路灯都会随手关掉(不耗时间),所以我们可以确定,若i点和j点的路灯已经关闭,那么区间i...j的路灯已经全部关闭,而且关完后,最优策略一定是在点i处或者点j处。

    这和上一题就很像了,用dp[i][j]表示把区间i...j的路灯全部关闭所有的最小电量。然后dp[i][j][0]表示关完后在i点时的最小电量,dp[i][j][1]表示关完后在j点时的最小电量。

    最后想一下动态转移方程,dp[i][j][0]可以从dp[i+1][j][0]和dp[i+1][j][1]转移而来,dp[i][j][1]可以从dp[i][j-1][0]和dp[i][j-1][1]转移而来。

    怎样计算呢?很显然是原来的dp值再加上关第i盏灯或第j盏灯要付出的代价。

    代价怎么求?

    我们很显然能作差求出距离(所用的时间),我们还需要知道到目前为止剩下的还未关的灯的功率和,因为已经关了的灯一定在某一区间内,然后又要求和,所以很自然地就想到了前缀和。

    最后的最后,last but not least,重要的事情说三遍:

    细节,细节,细节!

    AC代码

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 int n,a[105],w[105],dp[105][105][2],now,sum[105];
     5 int main()
     6 {
     7     cin>>n>>now;
     8     memset(dp,0x3f,sizeof(dp));
     9     for(int i=1;i<=n;i++){
    10         cin>>a[i]>>w[i];
    11         sum[i]=sum[i-1]+w[i];
    12     }
    13     dp[now][now][0]=dp[now][now][1]=0;
    14     for(int len=2;len<=n;len++){
    15         for(int i=max(1,now-len+1);i<=min(now,n);i++){
    16             int j=i+len-1;
    17             if(j>n) break;
    18             dp[i][j][0]=min(dp[i+1][j][0]+(sum[i]+sum[n]-sum[j])*(a[i+1]-a[i]),dp[i+1][j][1]+(sum[i]+sum[n]-sum[j])*(a[j]-a[i]));
    19             dp[i][j][1]=min(dp[i][j-1][0]+(sum[i-1]+sum[n]-sum[j-1])*(a[j]-a[i]),dp[i][j-1][1]+(sum[i-1]+sum[n]-sum[j-1])*(a[j]-a[j-1]));
    20         }
    21     }
    22     cout<<min(dp[1][n][0],dp[1][n][1]);
    23     return 0;
    24 }
  • 相关阅读:
    java 日志框架的选择Log4j->SLF4j->Logback
    linux上的常用命令
    Zookeeper配置Kafka
    分布式日志收集框架Flume
    Spark Streaming简介
    Spring Cloud学习笔记之微服务架构
    IntelliJ IDEA学习记录
    firefox插件-自动化测试工具-selenium IDE
    大数据01
    使用java开发spark的wordcount程序(多种实现)
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/12375381.html
Copyright © 2020-2023  润新知