這道題我並沒有完全理解他那個蛋疼的迴圈是什麼意思,這裡只有粘一篇寫的特別棒的題解了:
這是一道區間型的動態規劃題;
我主要是對前方的一些dp題解補充一些小細節。
既然是動規,那麼首先講一下常用的填表法和刷表法:
填表法就是利用狀態轉移方程和上乙個狀態來推導出現在的狀態(相當於知道已知條件,將答案填入)
刷表法就是利用當前的狀態,把有關聯的下一狀態都推出來。
這道題我選用的是填表法。
理解一下題目大意:
關燈不需要額外的時間,經過了燈就關了。但是可能折返回去關某乙個大燈會比繼續往下走關接下來的乙個小燈更優,
那麼可以得到兩種狀態(沿著當前方向繼續往下走,改變方向回去關燈)。
我們需要得到的整個關燈過程中的最優值(最小耗能)
那麼要設計的狀態轉移方程中肯定有兩種方案(折返的,不撞牆不回頭的)
又因為如果想要關某一區間的燈的過程中耗能最小,所以可以轉換成乙個個區間來寫:
去關某一區間的燈,那麼整條街道上除了這一區間的燈會逐漸滅掉其他肯定會全亮。
那麼我們把f[i][j]記為當從i到j的燈都熄滅後剩下的燈的總功率。
再進一步:f[i][j][0]表示關掉i到j的燈後,老張站在i端點,f[i][j][1]表示關掉[i][j]的燈後,老張站在右端點
(i為左端點,j為右端點)
又f[i][j][0]會由兩種方案推導而來(上面有寫。):折返回來關i,j的燈、由i+1深入,繼續關第i盞燈從而擴充套件到(i,j);
所以得到狀態轉移方程:
f[i][j][0] = min ( f[i+1][j][0] + ( a[i+1] - a[i] ) * ( sum[i] + sum[n] - sum[j] ) , f[i+1][j][1] + ( a[j]-a[i] ) * ( sum[i]+sum[n]-sum[j]) );
f[i][j][1] = min ( f[i][j-1][0] + ( a[j] - a[i] ) * ( sum[i-1] + sum[n] - sum[j-1] ) , f[i][j-1][1] + ( a[j]-a[j-1] ) * ( sum[i-1] + sum[n] - sum[j-1] ) );
(列舉現在的路燈l(2-n,因為第c位的路燈已經被關了),i+l-1<=n(路只有這麼長),j=i+l-1(右端點))
因為最後不知道老張到底站在左端點最優還是站在右端點最優
所以在f[1][n][0]和f[1][n][1]中取min輸出。
下附**(含解釋)
#include #include using namespace std;
const int maxm=60;
int a[maxm],b[maxm],sum[maxm],n,m,c;
int f[maxm][maxm][2];
int main()
int ans=min(f[1][n][0],f[1][n][1]);
printf("%d",ans);
return 0;
}
解題報告 關路燈
這道題我並沒有完全理解他那個蛋疼的迴圈是什麼意思,這裡只有粘一篇寫的特別棒的題解了 這是一道區間型的動態規劃題 我主要是對前方的一些dp題解補充一些小細節。既然是動規,那麼首先講一下常用的填表法和刷表法 填表法就是利用狀態轉移方程和上乙個狀態來推導出現在的狀態 相當於知道已知條件,將答案填入 刷表法...
關路燈 power 解題報告
源程式名 power.pas c cpp 可執行檔名 power.exe 輸入檔名 power.in 輸出檔名 power.out 問題描述 某一村莊在一條路線上安裝了n盞路燈,每盞燈的功率有大有小 即同一段時間內消耗的電量有多有少 老張就住在這條路中間某一路燈旁,他有一項工作就是每天早上天亮時一盞...
區間DP 關路燈
給你一條直線,直線上有 n 個點,每個點每秒都有消耗能量,現在再給你個點 m 代表你當前的位置,現在你要去碰這些點,當你碰到這些點時,這些點就不再消耗能量,你的速度是1m s,現在讓你求碰完這些點消耗能量最少,且最少值為多少 看了一下題,哎,這題還寫了不能用貪心,那就dp咯,還發現每次只能碰乙個點,...