某一村莊在一條路線上安裝了n盞路燈,每盞燈的功率有大有小(即同一段時間內消耗的電量有多有少)。老張就住在這條路中間某一路燈旁,他有一項工作就是每天早上天亮時一盞一盞地關掉這些路燈。
為了給村里節省電費,老張記錄下了每盞路燈的位置和功率,他每次關燈時也都是盡快地去關,但是老張不知道怎樣去關燈才能夠最節省電。他每天都是在天亮時首先關掉自己所處位置的路燈,然後可以向左也可以向右去關燈。開始他以為先算一下左邊路燈的總功率再算一下右邊路燈的總功率,然後選擇先關掉功率大的一邊,再回過頭來關掉另一邊的路燈,而事實並非如此,因為在關的過程中適當地調頭有可能會更省一些。
現在已知老張走的速度為1m/s,每個路燈的位置(是乙個整數,即距路線起點的距離,單位:m)、功率(w),老張關燈所用的時間很短而可以忽略不計。
請你為老張編一程式來安排關燈的順序,使從老張開始關燈時刻算起所有燈消耗電最少(燈關掉後便不再消耗電了)。
第一行是兩個數字n(0乙個資料,即最少的功耗(單位:j,1j=1w·s)。
532
103205
206308
10
270
每個測試點1s
此時關燈順序為3 4 2 1 5
傳送門
/*
經典好題~乙個dp必學題叭~~
首先我們要想怎麼樣才能完整表示乙個狀態~
我們可以看到的
如果去關燈關掉了區間[l,r]的燈
那麼最後關的一盞不是l就是r
所以我們可以想到用這樣乙個狀態表示
f[l][r][k]表示關掉區間[l,r]的所有燈所需要的最小代價
其中k=0表示現在人在l即最後關的燈是l
k=1表示現在人在r即最後關的是r這盞燈
這樣就設計出了乙個正確無誤的狀態
先考慮初值
f[i][i]就是從起始位置直接到i開i燈的代價
那麼我們來考慮狀態轉移
我們知道f[l][r][0]表示的是最後關掉了l這盞燈使得[l,r]全部都關了
那麼對應的上乙個狀態必然是已經關掉了[l+1,r]區間所有的燈
那麼我們就要考慮到到底是f[l+1][r][0]轉移過來更優還是f[l+1][r][1]更優
即考慮到了左右兩種完全的情況
那麼很容易有狀態轉移
f[i][j][0]=min(f[i+1][j][0]+(sump-(s[i+1][j]))*getd(i,i+1),
f[i+1][j][1]+(sump-(s[i+1][j]))*getd(i,j));
其中我們已經預處理出sump表示所有燈總功率
s[i]表示1...i的所有燈的功率然後用字首和可以算出s[i+1][j]
這個轉移仔細理解一下就好了
同理就可以得出f[i][j][1]的轉移
遞推的時候外層迴圈列舉長度內層迴圈列舉起點
最後取f[1][n][0]和f[1][n][1]的更優值就好了~
時間複雜度o(n^2)
可以直接秒殺~
*/
#include
//關路燈
#include
#include
#include
using
namespace std;
const
int maxn =52;
int n, c;
int x[maxn]
, w[maxn]
, sump;
int dp[maxn]
[maxn][2
], s[maxn]
;// dp[i][j] 選擇區間[i, j]時, 最小消耗
// time[i][j] 表示從i到j的時間
// s[i]功率字首和
intgetd
(int a,
int b)
voiddp(
)}cout <<
min(dp[1]
[n][0]
, dp[1]
[n][1]
)<< endl;
}int
main()
// s[i][j] = s[j] - s[i - 1];dp(
);system
("pause");
return0;
}
動態規劃 區間
真是乙個思維巧妙的毒瘤題。因此我們直接利用上面的性質來dp.設f i j f i j f i j 表示線段按右端點排序後第i ii條,j,rj j,r j j,rj 只被覆蓋了一次的最小代價,1,rj 1,r j 1,rj 全部被覆蓋的方案數。那麼,我們需要根據上乙個線段j jj和i ii的位置關係...
動態規劃 區間型
概述 最長的回文序列 取數是否必勝 給定乙個序列 字串,進行一些操作,最後一步會將序列 字串去頭 去尾 剩下的會是乙個區間 i,j 狀態自然定義為f i j 表示面對子串行 i,j 時的最優性質 1.題目描述 1.給定乙個字串s,長度是n,找到它最長的回文子串行的長度 例子 輸入 bbbab 輸出 ...
模板 動態規劃 區間dp
因為昨天在codeforces上設計的區間dp錯了 錯過了上紫的機會 覺得很難受。看看學長好像也有學,就不用看別的神犇的了。區間dp處理環的時候可以把序列延長一倍。for int len 1 len n len 首先,使用四邊形優化要滿足下面的性質 當小區間包含在大區間中,則小區間的成本不高於大區間...