2014百度之星資格賽第二題

題目:

Problem Description
有很多從磁盤讀取數據的需求,包括順序讀取、隨機讀取。爲了提高效率,需要人爲安排磁盤讀取。然而,在現實中,這種做法很複雜。我們考慮一個相對簡單的場景。
磁盤有許多軌道,每個軌道有許多扇區,用於存儲數據。當我們想在特定扇區來讀取數據時,磁頭需要跳轉到特定的軌道、具體扇區進行讀取操作。爲了簡單,我們假設磁頭可以在某個軌道順時針或逆時針勻速旋轉,旋轉一週的時間是360個單位時間。磁頭也可以隨意移動到某個軌道進行讀取,每跳轉到一個相鄰軌道的時間爲400個單位時間,跳轉前後磁頭所在扇區位置不變。一次讀取數據的時間爲10個單位時間,讀取前後磁頭所在的扇區位置不變。磁頭同時只能做一件事:跳轉軌道,旋轉或讀取。
現在,需要在磁盤讀取一組數據,假設每個軌道至多有一個讀取請求,這個讀取的扇區是軌道上分佈在 0到359內的一個整數點扇區,即軌道的某個360等分點。磁頭的起始點在0軌道0扇區,此時沒有數據讀取。在完成所有讀取後,磁頭需要回到0軌道0扇區的始點位置。請問完成給定的讀取所需的最小時間。
Input
輸入的第一行包含一個整數M(0<M<=100),表示測試數據的組數。
對於每組測試數據,第一行包含一個整數N(0<N<=1000),表示要讀取的數據的數量。之後每行包含兩個整數T和S(0<T<=1000,0<= S<360),表示每個數據的磁道和扇區,磁道是按升序排列,並且沒有重複。
 Output
對於每組測試數據,輸出一個整數,表示完成全部讀取所需的時間。
 Sample Input
3
1
1 10
3
1 20
3 30
5 10
2
1 10
2 11
 Sample Output
830
4090
1642
 

該題目是比較經典的雙調歐幾里德旅行商問題。用動態規劃來做。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
const int maxn=1000+5;
int inf=1<<29;
int dp[maxn][maxn];
int d[maxn][maxn];
int x[maxn],y[maxn];
int dist(int i,int j){
    return abs(x[i]-x[j])*400+min(abs(y[i]-y[j]),360-abs(y[i]-y[j]));
}
int main(){
    //freopen("a.txt","r",stdin);
    int n;
        int kase;
        cin>>kase;
    while(kase--){
        cin>>n;
        n++;
        for(int i=2;i<=n;i++)
            scanf("%d%d",&x[i],&y[i]);
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                d[j][i]=d[i][j]=dist(i,j);
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                dp[i][j]=inf;
        dp[2][3]=dp[1][3]=d[1][2]+d[2][3]+d[1][3];
        for(int i=4;i<=n;i++)
            for(int j=1;j<i-1;j++){
                    dp[j][i]=min(dp[j][i],dp[j][i-1]+d[j][i]+d[i][i-1]-d[i-1][j]);
                dp[i-1][i]=min(dp[i-1][i],dp[j][i]);
            }
        int ans=inf;
        if(n==2)
            ans=2*dist(1,2);
        for(int i=1;i<=n-1;i++)
            ans=min(ans,dp[i][n]);
        printf("%d\n",ans+(n-1)*10);
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章