Dr.Kong設計的機器人卡多愈來愈聰明。最近市政公司交給卡多一項任務,天天早晨5:00開始,它負責關掉ZK大道右側上全部的路燈。php
卡多每到早晨5:00準會在ZK大道上某盞路燈的旁邊,而後他開始關燈。每盞燈都有必定的功率,機器人卡多有着自覺的節能意識,它但願在關燈期間,ZK大道右側上全部路燈的耗電量總數是最少的。ios
機器人卡多以1m/s的速度行走。假設關燈動做不須要花費額外的時間,由於當它經過某盞路燈時就順手將燈關掉。測試
請你編寫程序,計算在給定路燈設置,燈泡功率以及機器人卡多的起始位置的狀況下,卡多關燈期間,ZK大道上全部燈耗費的最小能量。spa
4 3 2 2 5 8 6 1 8 7
56
解題思路:.net
本題是一道Dynamic Programming的題目,機器人關燈要麼是去左邊關燈,或者是去右邊關燈,也即要關閉的下一個路燈要麼是從已關閉路段的左端過去的,要麼是從已關閉的路段的右端過去的,定義:設計
DP[i][j][0]表示i到j的路燈都已經關閉,機器人在路燈i的位置,此時已經消耗的最小電能code
DP[i][j][1]表示i到j的路燈都已經關閉,機器人在路燈j的位置,此時已經消耗的最小電能blog
則狀態轉移式:內存
DP[i][j][0] = min(DP[i+1][j][0]+[i+1,j]路段之外未關閉路燈在機器人從i+1走的i期間消耗的電能,DP[i+1][j][1]+[i+1,j]路段之外未關閉路燈在機器人從j走到i期間消耗的電能)get
DP[i][j][1] = min(DP[i][j-1][0]+[i,j-1]路段之外未關閉路燈在機器人從i走到j期間消耗的電能,DP[i][j-1][1]+[i,j-1]路段之外未關閉路燈在機器人從j-1走到j期間消耗的電能)
AC代碼:
1 #include<algorithm> 2 #include<cstdio> 3 #include<iostream> 4 #include<cstring> 5 using namespace std; 6 const int N = 1010; 7 int dp[N][N][2],dw[N][N],st[N],co[N]; 8 int main() 9 { 10 int n,s,v,sum; 11 while(scanf("%d",&n)!=EOF) 12 { 13 memset(dw,0,sizeof(dw)); 14 sum = 0; 15 scanf("%d",&v); 16 for(int i =1; i<=n; i++) 17 { 18 scanf("%d %d",&st[i],&co[i]); 19 sum =sum+co[i]; 20 } 21 for(int i=1;i<=n;i++) 22 for(int j=i;j<=n;j++) 23 dw[i][j] = dw[i][j-1]+co[j]; 24 for(int i = v-1; i>0; i--) 25 { 26 dp[i][v][0] = dp[i+1][v][0]+(sum-dw[i+1][v])*(st[i+1]-st[i]); 27 dp[i][v][1] = dp[i][v][0] +(sum-dw[i][v])*(st[v]-st[i]); 28 } 29 for(int j =v+1; j<=n; j++) 30 { 31 dp[v][j][1] =dp[v][j-1][1]+(sum-dw[v][j-1])*(st[j]-st[j-1]); 32 dp[v][j][0] =dp[v][j][1]+(sum-dw[v][j])*(st[j]-st[v]); 33 } 34 35 for(int i =v-1;i>0;i--) 36 { 37 for(int j =v+1; j<=n; j++) 38 { 39 dp[i][j][0] = min(dp[i+1][j][0]+(sum-dw[i+1][j])*(st[i+1]-st[i]), 40 dp[i+1][j][1]+(sum-dw[i+1][j])*(st[j]-st[i])); 41 dp[i][j][1] = min(dp[i][j-1][0]+(sum-dw[i][j-1])*(st[j]-st[i]), 42 dp[i][j-1][1]+(sum-dw[i][j-1])*(st[j]-st[j-1])); 43 } 44 } 45 46 printf("%d\n", min(dp[1][n][0], dp[1][n][1])); 47 } 48 return 0; 49 }