zoukankan      html  css  js  c++  java
  • 【中学高级水题本】关路灯

    【中学高级本】关路灯

    Description

    某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少)。老冯就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯。 
    为了给村里节省电费,老冯记录下了每盏路灯的位置和功率,他每次关灯时也都是尽快地去关,但是老冯不知道怎样去关灯才能够最节省电。他每天都是在天亮时首先关掉自己所处位置的路灯,然后可以向左也可以向右去关灯。开始他以为先算一下左边路灯的总功率再算一下右边路灯的总功率,然后选择先关掉功率大的一边,再回过头来关掉另一边的路灯,而事实并非如此,因为在关的过程中适当地调头有可能会更省一些。 
    现在已知老冯走的速度为1m/s,每个路灯的位置(是一个整数,即距路线起点的距离,单位:m)、功率(W),老冯关灯所用的时间很短而可以忽略不计。 
    请你为老冯编一程序来安排关灯的顺序,使从老冯开始关灯时刻算起所有灯消耗电最少(灯关掉后便不再消耗电了)。

    Input

    第一行是两个数字n(0,表示路灯的总数)和c(1<=c<=n老冯所处位置的路灯号); 
    接下来n行,每行两个数据,表示第1盏到第n盏路灯的位置和功率。

    Output

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

    Sample Input

    5 3 
    2 10 
    3 20 
    5 20 
    6 30 
    8 10

    Sample Output

    270

    Hint

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

    Source

    动态规划 ,回溯, 贪心

    思路:裸的dp。因为老冯关灯不需要时间,所以关的灯总是一个区间[l,r]。同理老冯的位置也只会在l,r中一个,所以定义f[k][l][r]为老冯关了l到r的灯,k为0就在l位置,为1就在r位置。老冯每次只能关灯l-1或r+1,由此得转移为

    f[0][l][r]+distance(l,l-1)*(W[1..l-1]+w[r+1..n])->f[0][l-1][r]

    f[0][l][r]+distance(l,r+1)*(W[1..l-1]+w[r+1..n])->f[1][l][r+1]

    f[1][l][r]+distance(r,l-1)*(W[1..l-1]+w[r+1..n])->f[0][l-1][r]

    f[1][l][r]+distance(r,r+1)*(W[1..l-1]+w[r+1..n])->f[1][l][r+1]

    然后敲代码就行了,O(n2)

     1 // It is made by XZZ
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #define File
     6 #define Fname "power"
     7 using namespace std;
     8 #define rep(a,b,c) for(rg int a=b;a<=c;a++)
     9 #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    10 #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    11 #define il inline
    12 #define rg register
    13 #define vd void
    14 typedef long long ll;
    15 il int gi(){
    16     rg int x=0;rg char ch=getchar();
    17     while(ch<'0'||ch>'9')ch=getchar();
    18     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    19     return x;
    20 }
    21 int f[2][1001][1001];
    22 int d[1001],w[1001];
    23 il int min(int a,int b,int c){return min(a,min(b,c));}
    24 int main(){
    25     rg int n=gi(),m=gi();
    26     rep(i,1,n)d[i]=gi(),w[i]=gi()+w[i-1];
    27     memset(f,127/2,sizeof f);f[0][m][m]=f[1][m][m]=0;
    28     rep(siz,1,n)//siz==r-l+1
    29     rep(l,max(1,m-siz+1),m){
    30             rg int r=siz+l-1;
    31         if(r>n)break;
    32         if(l-1)f[0][l-1][r]=min(f[0][l-1][r],f[0][l][r]+(d[l]-d[l-1])*(w[l-1]+w[n]-w[r]),f[1][l][r]+(d[r]-d[l-1])*(w[l-1]+w[n]-w[r]));
    33         if(r-n)f[1][l][r+1]=min(f[1][l][r+1],f[0][l][r]+(d[r+1]-d[l])*(w[l-1]+w[n]-w[r]),f[1][l][r]+(d[r+1]-d[r])*(w[l-1]+w[n]-w[r]));
    34     }
    35     printf("%d
    ",min(f[0][1][n],f[1][1][n]));
    36     return 0;
    37 }
    View Code

    PS.为什么要因为考试发一道水题题解。。。。。

  • 相关阅读:
    HDU 3951 (博弈) Coin Game
    HDU 3863 (博弈) No Gambling
    HDU 3544 (不平等博弈) Alice's Game
    POJ 3225 (线段树 区间更新) Help with Intervals
    POJ 2528 (线段树 离散化) Mayor's posters
    POJ 3468 (线段树 区间增减) A Simple Problem with Integers
    HDU 1698 (线段树 区间更新) Just a Hook
    POJ (线段树) Who Gets the Most Candies?
    POJ 2828 (线段树 单点更新) Buy Tickets
    HDU 2795 (线段树 单点更新) Billboard
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7202445.html
Copyright © 2011-2022 走看看