題目:
題意:給定n盞燈的位置和功率,初始時站在第c盞處。
關燈不需要時間,走的速度是1單位/秒。問把所有的燈關掉,最少功率是多少。
思路:看上去是區間dp還挺清楚的。因為關燈不需要時間,既然路過了就順便關了吧。所以肯定是中間某一段的燈都被關了,兩端各有一段亮著。
所以我們可以用$dp[i][j]$表示i~j號燈都被關了。但是最後關的是$i$還是$j$還是有差別的,所以還需要一維來標記。
因為需要區間和,所以再用$sum$維護區間字首和
最後得到狀態轉移方程
$dp[i][j][0] = min(dp[i+1][j][0] + (pos[i+1] - pos[i]) * (sum[i] + sum[n] - sum[j]), dp[i+1][j][1] + (pos[j] - pos[i]) * (sum[i] + sum[n] - sum[j]))$
$dp[i][j][1] = min(dp[i][j-1][1] + (pos[j] - pos[j - 1]) * (sum[n] - sum[j - 1] + sum[i - 1]), dp[i][j-1][0] + (pos[j] - pos[i]) * (sum[n] - sum[j - 1] + sum[i - 1]))$
要注意兩個情況燈的功率是不同的。
初始情況和結束情況都比較好判斷。
中間更新的話其實就是列舉關了的燈的數量,然後列舉起點就可以了。
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include10 #include11 #include12
13#define inf 0x7fffffff
14using
namespace
std;
15 typedef long
long
ll;16 typedef pairpr;
1718
intn;
19const
int maxn = 55;20
intc;
21int
light[maxn], sum[maxn], pos[maxn];
22int dp[maxn][maxn][2
];23
24int
main()
2532 dp[c][c][0] = dp[c][c][1] = 0;33
for(int num = 2; num <= n; num++)42}
4344 printf("
%d\n
", min(dp[1][n][0], dp[1][n][1
]));
4546 }
洛谷P1220 關路燈(區間dp)
某一村莊在一條路線上安裝了n盞路燈,每盞燈的功率有大有小 即同一段時間內消耗的電量有多有少 老張就住在這條路中間某一路燈旁,他有一項工作就是每天早上天亮時一盞一盞地關掉這些路燈。為了給村里節省電費,老張記錄下了每盞路燈的位置和功率,他每次關燈時也都是盡快地去關,但是老張不知道怎樣去關燈才能夠最節省電...
洛谷 P1220 關路燈 區間DP
某一村莊在一條路線上安裝了 n 盞路燈,每盞燈的功率有大有小 即同一段時間內消耗的電量有多有少 老張就住在這條路中間某一路燈旁,他有一項工作就是每天早上天亮時一盞一盞地關掉這些路燈。為了給村里節省電費,老張記錄下了每盞路燈的位置和功率,他每次關燈時也都是盡快地去關,但是老張不知道怎樣去關燈才能夠最節...
洛谷P1220關路燈 區間dp
某一村莊在一條路線上安裝了 n 盞路燈,每盞燈的功率有大有小 即同一段時間內消耗的電量有多有少 老張就住在這條路中間某一路燈旁,他有一項工作就是每天早上天亮時一盞一盞地關掉這些路燈。為了給村里節省電費,老張記錄下了每盞路燈的位置和功率,他每次關燈時也都是盡快地去關,但是老張不知道怎樣去關燈才能夠最節...