1. 程式人生 > >P1220 關路燈

P1220 關路燈

%d main center cnblogs 處理 省電 include 記錄 define

【P1220】關路燈 - 洛谷

https://www.luogu.org/problem/show?pid=1220

P1220 關路燈

題目描述

某一村莊在一條路線上安裝了n盞路燈,每盞燈的功率有大有小(即同一段時間內消耗的電量有多有少)。老張就住在這條路中間某一路燈旁,他有一項工作就是每天早上天亮時一盞一盞地關掉這些路燈。

為了給村裏節省電費,老張記錄下了每盞路燈的位置和功率,他每次關燈時也都是盡快地去關,但是老張不知道怎樣去關燈才能夠最節省電。他每天都是在天亮時首先關掉自己所處位置的路燈,然後可以向左也可以向右去關燈。開始他以為先算一下左邊路燈的總功率再算一下右邊路燈的總功率,然後選擇先關掉功率大的一邊,再回過頭來關掉另一邊的路燈,而事實並非如此,因為在關的過程中適當地調頭有可能會更省一些。

現在已知老張走的速度為1m/s,每個路燈的位置(是一個整數,即距路線起點的距離,單位:m)、功率(W),老張關燈所用的時間很短而可以忽略不計。

請你為老張編一程序來安排關燈的順序,使從老張開始關燈時刻算起所有燈消耗電最少(燈關掉後便不再消耗電了)。

輸入輸出格式

輸入格式:

文件第一行是兩個數字n(0<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,不必輸出這個關燈順序}

分析:

dp:

⑴每個路燈的花費為 ci*ti ,即功率乘以關閉的時間。

⑵所關掉的路燈是一個連續的區間,越過一個亮著的路燈而去關其他路燈顯然不是最優的。因為了連續區域可以用前綴和預處理。

F[i][j][0]表示區間i到j最後一個關的是第i盞燈所需最小電。F[i][j][1]表示區間i到j最後一個關的是第j盞燈所需的最小電。

狀態轉移:

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

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

技術分享

 1 #include<cstdio>  
 2 #include<cstring>  
 3 #define min(u,v) u<v ? u:v  
 4   
 5 int n,m,a[1005],c[1005],f[1005][1005][2];  
 6   
 7 int main()  
 8 {  
 9     scanf("%d%d",&n,&m);  
10     for(int i=1;i<=n;i++)  
11     {  
12         scanf("%d%d",&c[i],&a[i]);  
13         a[i]+=a[i-1];  
14     }  
15     memset(f,127,sizeof(f));  
16     f[m][m][0]=f[m][m][1]=0;  
17     for(int j=m;j<=n;j++)  
18       for(int i=j-1;i;i--)  
19       {  
20           //i,j區間外的燈在發光
21         //c[i+1]-c[i]表示時間 
22         f[i][j][0]=min(f[i+1][j][0]+(a[n]-(a[j]-a[i]))*(c[i+1]-c[i]),  
23                        f[i+1][j][1]+(a[n]-(a[j]-a[i]))*(c[j]-c[i]));  
24         f[i][j][1]=min(f[i][j-1][1]+(a[n]-(a[j-1]-a[i-1]))*(c[j]-c[j-1]),  
25                        f[i][j-1][0]+(a[n]-(a[j-1]-a[i-1]))*(c[j]-c[i]));  
26       }  
27     printf("%d\n",min(f[1][n][0],f[1][n][1]));  
28     return 0;  
29 }   

P1220 關路燈