histcat

histcat

P1220 關路燈

題目#

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

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

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

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

$1\le n\le50$,$1\le c\le n$。

題解#

這個題不太好想到動態規劃。

然後根據貪心,在從點 i 去關點 j 的路燈時,所有經過的路燈都會隨手關掉(不耗時間),所以我們可以確定,若 i 點和 j 點的路燈已經關閉,那麼區間 i...j 的路燈已經全部關閉,而且關完後,最優策略一定是在點 i 處或者點 j 處。

yinyuqin 大佬的話

所以我們設f[i][j][0/1]表示關完區間 i 到 j 的燈並且最後在 i/j

注意轉移的時候第 i/j 盞燈還沒滅,要消耗電量

問題#

初始化!!!

代碼#

#include<bits/stdc++.h>

using namespace std;

const int N = 55;

int read()
{
	int f = 1, x = 0;
	char ch = getchar();
	while(ch < '0' || ch > '9')
	{
		if(ch == '-') f = -1;
		ch = getchar();
	}

	while(ch >= '0' && ch <= '9')
	{
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return f * x;
}

struct U
{
	int pos, P;
}u[N];

int n, c;
int sum[N];
int f[N][N][2];//表示目前已經關了完了i——j盞燈,最後一盞關的是i/j的路徑組成的集合 屬性:最小電量 

int main()
{
	memset(f, 0x3f, sizeof f);
	n = read(), c = read();
	for(int i = 1;i <= n;i++)
	{
		u[i].pos = read(), u[i].P = read();
		sum[i] = sum[i - 1] + u[i].P;
	}

	f[c][c][1] = f[c][c][0] = 0;

	for(int L = 2; L <= n;L++)
	{
		for(int i = 1;i + L - 1 <= n;i++)
		{
			int j = i + L - 1;
			f[i][j][0] = min(f[i + 1][j][0] + (u[i + 1].pos - u[i].pos) * (sum[i]+sum[n]-sum[j]), f[i + 1][j][1] + (u[j].pos - u[i].pos) * (sum[i]+sum[n]-sum[j]));
			f[i][j][1] = min(f[i][j - 1][0] + (u[j].pos - u[i].pos) * (sum[i-1]+sum[n]-sum[j-1]), f[i][j - 1][1] + (u[j].pos - u[j - 1].pos) * (sum[i-1]+sum[n]-sum[j-1])); 
		}
	}


	cout << min(f[1][n][0], f[1][n][1]);
	return 0;
}
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。