1. 程式人生 > >萬聖節的小L

萬聖節的小L

萬聖節的小L

題目描述:

今天是萬聖節,小L同學開始了一年一度的討要糖果遊戲,但是在剛剛過去的比賽中小有成就的他打算給自己增加一點難度:如果沒有討到每一家的糖果就算輸。

已知小L共有n(n不大於10000)個鄰居,他們都在同一條街上(可以近似看成一條直線),第i個鄰居的座標是xi。L同學的媽媽會在一開始把他送到任意鄰居的門前。現在已知所有鄰居會在di時間後休息(休息以後不能再去打擾),求訪問完所有點的最短時間,如果無解輸出“No solution”。

輸入格式:

輸入第一行為一個正整數表示n,接下來n行,每行兩個用空格隔開的數,分別表示第i個鄰居的位置和休息時間。

輸出格式:

輸出一個數,表示最短時間,無解輸出“No solution”。

輸入樣例:

5
1 3
3 1
5 8
8 19
10 15

輸出樣例:

11


解題思路:

題目一看就是區間dp,但是資料範圍n<=10000,普通的dp[i][j]肯定炸,所以這道題的難點就是狀態轉移,滾動陣列正好能解決這個問題

定義一個數組dp[2][100010][2]:

第一維用來滾動,即輪換來記錄上一次的狀態和這一次的狀態 now=last,last^=1

第二維記錄位置

第三維記錄方向(0左,1右)

依題意可得轉移方程

dp[now][j][0]=min(dp[last][j+1][0]+x[j+1]-x[j],dp[last][j+1][1]+x[j+i]-x[j]);

dp[now][j][1]=min(dp[last][j][0]+x[j+i]-x[j],dp[last][j][1]+x[i+j]-x[i+j-1]);

 


 

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 #define inf 0x7ffffff
 5 using namespace std;
 6 int n,now,last,x[10010],d[10010],dp[2][10010][2],ans;
 7 int main()
8 { 9 scanf("%d",&n); 10 for(int i=1;i<=n;++i) 11 scanf("%d%d",&x[i],&d[i]); 12 for(int i=1;i<n;++i) 13 { 14 last=now; 15 now^=1; 16 for(int j=1;j<=n-i;++j) 17 { 18 dp[now][j][0]=min(dp[last][j+1][0]+x[j+1]-x[j],dp[last][j+1][1]+x[j+i]-x[j]); 19 dp[now][j][1]=min(dp[last][j][0]+x[j+i]-x[j],dp[last][j][1]+x[i+j]-x[i+j-1]); 20 if(dp[now][j][0]>=d[j]) 21 dp[now][j][0]=inf; 22 if(dp[now][j][1]>=d[i+j]) 23 dp[now][j][1]=inf; 24 } 25 } 26 ans=min(dp[now][1][0],dp[now][1][1]); 27 if(ans==inf) 28 printf("No solution"); 29 else 30 printf("%d",ans); 31 return 0; 32 }