1. 程式人生 > >多階段決策問題(UVa 116)

多階段決策問題(UVa 116)

memset i++ pri close names src 註意 algo ace

在回溯法中,每個決策對應於給一個節點產生新的子樹,而解的生成過程對應一顆解答樹,節點的層數就是下一個待填充位置$cur$。

在多階段決策的最優化問題,大多可以用dp解決,狀態轉移則類似於回溯法中的解答樹。

UVa 116

$d(i,j)$表示從第此處出發到達最後一列的最小和,要求字典序最小,就同時要記錄行號的最小值。

代碼:

技術分享圖片
 1 //
 2 //  main.cpp
 3 //  UVa 116
 4 //
 5 //  Created by Yanbin GONG on 12/3/2018.
 6 //  Copyright ? 2018 Yanbin GONG. All rights reserved.
 7 //
 8
9 #include <iostream> 10 #include <stdio.h> 11 #include <string> 12 #include <string.h> 13 #include <algorithm> 14 #include <cmath> 15 16 using namespace std; 17 18 int m,n; 19 int cell[15][105]; 20 int d[15][105]; 21 int path[15][105]; //記錄從該處應該走到的下一個點 22 int tmp;
23 int ans; 24 int startNode; 25 //int updown[3] = {-1,0,1}; 寫在dp中,方便改變狀態,滿足在上下邊時候的移動 26 27 28 int main(){ 29 while(cin>>n>>m){ 30 memset(d,0x3f,sizeof(d)); 31 ans = 0x3f3f3f3f; 32 for(int i=1;i<=n;i++){ 33 for(int j=1;j<=m;j++){ 34 cin>>cell[i][j];
35 } 36 d[i][m] = cell[i][m];//初始化邊界 37 } 38 //dp 39 for(int j=m;j>1;j--){ 40 41 for(int i=1;i<=n;i++){ 42 int updown[3] = {i-1,i,i+1}; //表示接下來處在的行 43 if(i==1) updown[0] = n; 44 if(i==n) updown[2] = 1; 45 //排序找到最小字典序的核心代碼!因為這個WA了 46 sort(updown,updown+3); //排序找到最小字典序的核心代碼!因為這個WA了 47 //排序找到最小字典序的核心代碼!因為這個WA了 48 for(int k=0;k<3;k++){ 49 tmp = d[i][j] + cell[updown[k]][j-1]; //到[][j-1]的總成本 50 if(tmp<d[updown[k]][j-1]){ 51 d[updown[k]][j-1] = tmp; 52 path[updown[k]][j-1] = i;//反向記錄從[][j-1]走到[i][j] 53 } 54 } 55 } 56 } 57 //找到最優解的開始 58 for(int i=1;i<=n;i++){ 59 if(ans>d[i][1]){ 60 ans = d[i][1]; 61 startNode = i; 62 } 63 } 64 //print 65 printf("%d",startNode); 66 int nextNode = path[startNode][1]; 67 for(int j=1;j<=m;j++){ 68 printf(" %d",nextNode); 69 nextNode = path[nextNode][j]; 70 } 71 printf("\n%d\n",ans); 72 } 73 return 0; 74 }
View Code

這題要註意將$updown$更新後重新排序一遍,這樣才能確定找到的字典序是最小的

多階段決策問題(UVa 116)