zoj 1196區間動態規劃

來源:互聯網
上載者:User

Sample Input

6 356121920270 0

Sample Output

Chain 1Depot 1 at restaurant 2 serves restaurants 1 to 3Depot 2 at restaurant 4 serves restaurants 4 to 5Depot 3 at restaurant 6 serves restaurant 6Total distance sum = 8

Source

Southwestern European Regional Contest 1998  

【題目大意】

一條公路上有n個旅館,選出其中k個設定倉庫,一個倉庫可服務若干個旅館,一個旅館只需一個倉庫服務。問在哪幾個旅館設定倉庫,每個倉庫服務哪些旅館,可使得旅館到倉庫的總距離最小,並求出總距離(長理只要求求最後一步)。

【資料範圍】

1 <= n <= 200, 1 <= k <= 30, k <= n

【解題思想】

1、此題屬於明顯動態規劃題,關鍵點是找狀態轉移方程。

2、可以用sum[i][j]表示前i個旅館,設定j個倉庫得到的距離和最小值,那麼sum[n][k]即為所求。

3、找sum[i][j]的子結構,假設前j-1個倉庫服務第1個到第k個旅館,則最後一個倉庫服務第k+1個到第i個旅館。

4、可以用one[i][j]表示一個倉庫服務第i個到第j個旅館,到這個倉庫距離和的最小值。

5、則得到狀態轉移方程:sum[i][j]=min(sum[k][j-1]+one[k+1][i]) (j-1<=k<=i-1,min表示所有k取值得到的值中的最小值)。

6、問題轉換為了求one[i][j],即在第i到第j家旅館中設定一個倉庫的總距離。

7、假設i到j共有奇數家旅館,我們嘗試將倉庫放置在中間旅館,即旅館(i+j)/2,假設將倉庫左移距離x,則右半邊所有旅館到倉庫距離均加x,而只有部分左半邊旅館距離減少了x,剩下的減少均小於x,甚至不減少。因此可以得到,將倉庫從中間位置左移到任何位置總距離都會增加,右移同理,因此倉庫放到旅館(i+j)/2最合適。

8、假設i到j共有偶數家旅館,容易得到將倉庫放到(i+j-1)/2和(i+j+1)/2得到的總距離相等(對稱性),若將倉庫放到(i+j-1)/2,並左移,則用7相似的想法可得知總距離增大,右移情況同理,由此得知倉庫放到(i+j-1)/2這個位置即可滿足總距離最小。

9、由7、8得到one[i][j]實際上時將倉庫放到(i+j)/2取整位置可得到最小的總距離。

10、資料範圍較小,我們可以計算出一切one[i][j]的組合。

 

11、由於poj還要求輸出在哪幾個旅館設定倉庫,每個倉庫服務哪些旅館,因此還需要儲存動態規劃路徑。

12、可用at[i][j],from[i][j],to[i][j]分別表示sum[i][j]得到最小值時最後一個倉庫的位置、服務的起始位置和服務的終止位置。

13、通過遞迴輸出結果。

 

#include<stdio.h>#include<algorithm>#include<string.h>using namespace std;const int INF=100000000;int r[300],sum[300][40],one[300][300];int from[300][40],to[300][40],at[300][40];int output(int i,int j){    if(j<=0||i<=0)return 1;    int num=output(from[i][j]-1,j-1);    printf("Depot %d at restaurant %d serves ",num,at[i][j]);    if(from[i][j]==to[i][j])printf("restaurant %d\n",from[i][j]);       else printf("restaurants %d to %d\n",from[i][j],to[i][j]);    return num+1;}    int main(){    int n,K,i,j,k,middle;    int iCase=0;    while(scanf("%d%d",&n,&K)!=EOF)    {   iCase++;        if(n==0&&K==0)break;        for(i=1;i<=n;i++)  scanf("%d",&r[i]);        memset(one,0,sizeof(one));        memset(sum,0,sizeof(sum));        for(i=1;i<=n;i++)        {  for(j=1;j<=n;j++)  {                  middle=(i+j)/2;                   //for(k=i;k<middle;k++)one[i][j]+=r[middle]-r[k];                   //for(k=middle+1;k<=j;k++)one[i][j]+=r[k]-r[middle];       for(k=i;k<=j;k++)one[i][j]+=abs(r[middle]-r[k]);                         }                }          for(i=1;i<=n;i++)  sum[i][0]=INF; for(i=1;i<=n;i++)        {     for(j=1;j<=i&&j<=K;j++)               {         sum[i][j]=INF;                  for(k=j-1;k<=i-1;k++)                  {                          int tmp=sum[k][j-1]+one[k+1][i];                      if(tmp<sum[i][j])                      {                          sum[i][j]=tmp;                          from[i][j]=k+1;                          to[i][j]=i;                          at[i][j]=(k+1+i)/2;                      }                      }                          }                    }            printf("Chain %d\n",iCase);        output(n,K);        printf("Total distance sum = %d\n\n",sum[n][K]);            }           return 0;} 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.