POI 1997 最優旅行計劃 Cheap travels

我是我做得POI的第一道題,應該也是最簡單的一道題了。簡單的動態規劃問題,兩問是類似的,僅僅優先選擇的條件不同。

我僅說下第一問,狀態設定 F[i]到地i個旅店時住宿的最小費用 G[i]到地i個旅店時住宿的最小過夜次數

狀態轉移方程 F[i]=Min{ F[j] | S[i]-S[j]<=800 } + Cost[i] G[i]=Min{ G[j] | { F[j] | S[i]-S[j]<=800 }} + 1

邊界條件 F[0]=G[0]=0

目標解 F[N+1] G[N+1]

#include <iostream>

const int MAX=1002;
const int DIST=800;
const int INF=0x7FFFFFFF;

using namespace std;

int N,T,A;
int S[MAX],F[MAX],G[MAX],C[MAX],H[MAX],Ans[MAX];

void init()
{
    int i;
    freopen("tan.in","r",stdin);
    freopen("tan.out","w",stdout);
    scanf("%d%d",&T,&N);
    for (i=1;i<=N;i++)
    {
        scanf("%d%d",&S[i],&C[i]);
    }
    S[0]=C[0]=C[N+1]=0;
    S[N+1]=T;
}

void dynamic1()
{
    int i,j;
    F[0]=G[0]=0;
    for (i=1;i<=N+1;i++)
    {
        F[i]=G[i]=INF;
        H[i]=0;
    }
    for (i=1;i<=N+1;i++)
    {
        for (j=i-1;j>=0 && S[i]-S[j]<=DIST;j--)
        {
            if (F[j]+C[i]<F[i])
            {
                F[i]=F[j]+C[i];
                G[i]=G[j]+1;
                H[i]=j;
            }
            else if (F[j]+C[i]==F[i] && G[j]+1<G[i])
            {
                G[i]=G[j]+1;
                H[i]=j;
            }
        }
    }
    A=0;
    for (i=N+1;H[i];i=H[i])
    {
        Ans[++A]=H[i];
    }
    for (i=A;i>=2;i--)
    {
        printf("%d ",S[Ans[i]]);
    }
    printf("%dn",S[Ans[1]]);
}

void dynamic2()
{
    int i,j;
    F[0]=G[0]=0;
    for (i=1;i<=N+1;i++)
    {
        F[i]=G[i]=INF;
        H[i]=0;
    }
    for (i=1;i<=N+1;i++)
    {
        for (j=i-1;j>=0 && S[i]-S[j]<=DIST;j--)
        {
            if (G[j]+1<G[i])
            {
                F[i]=F[j]+C[i];
                G[i]=G[j]+1;
                H[i]=j;

            }
            else if (G[j]+1==G[i] && F[j]+C[i]<F[i])
            {
                F[i]=F[j]+C[i];
                H[i]=j;
            }
        }
    }
    A=0;
    for (i=N+1;H[i];i=H[i])
    {
        Ans[++A]=H[i];
    }
    for (i=A;i>=2;i--)
    {
        printf("%d ",S[Ans[i]]);
    }
    printf("%d",S[Ans[1]]);
}

int main()
{
    init();
    dynamic1();
    dynamic2();
    return 0;
}
最優旅行計劃
某教練想做一次旅行,將走高速公路,因爲在路旁有一些價格實惠的旅館,這樣能沿途花費盡可能的少,不考慮開始點和到達點。爲了安全起見,他每天只在白天行走,晚上在旅館住宿,並且一天的路程不超過800公里。旅行社根據調查,給出了沿路旅館的相關信息,包括每個旅館離出發點的距離和該旅館的價格,當然,爲了整個旅行的順利完成,任意兩個旅館之間的距離都將在800公里以內。 
你的任務是編寫一個程序,在旅行距離內,對給定的輸入數據,求出,
1)1)費用最少的旅行計劃(即中途住宿的費用之和),如果有多個最小費用計劃,則取日程最短的計劃。
2)2)日程最短的旅行計劃(中途在旅館住宿的天數),如果有多個最短日程計劃,則取費用最少的計劃。
輸入
在文本文件TAN.IN 中的第一行有用一個空格分隔的兩個正整數,第一個整數d 表示旅行的距離(單位:公里)。第二個整數 h表示沿途旅社的數目, d <= 16000, h <= 1000。接下來的h行,每行有兩個用單個空格分隔的正整數,說明某旅社的相關信息,第一個正整數表示離起點的距離(單位:公里),第二個正整數表示該旅社的價格。價格不會超過1000。 
輸出
在文本文件TAN.OUT的第一行輸出費用最少的旅行計劃;第二行輸出日程最短的旅行計劃;旅行計劃由在所有住宿的旅社組成,對每個旅社,只輸出離出發點的距離即可,相鄰兩個數之間用一個空格分隔。
輸入示例
2000 7
100 54
120 70
400 17
700 38
1000 25
1200 18
1440 40
輸出示例
400 1200
400 1200

相關日誌