116 - Unidirectional TSP

来源:互联网 发布:centos iso 本地yum 编辑:程序博客网 时间:2024/04/28 18:02

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=114&page=show_problem&problem=52

题目意思很明确,并且这一题的递归方程很好写,只不过需要注意的是对于字典序的理解。在更新路径的时候要不断的比较字典序,即要从头到尾的比较而不是仅仅比较前驱。

代码如下:

/*ID: csuchenanPROG: uva 116 - Unidirectional TSPLANG: C++algorithm: dynamic program*/#include<iostream>#include<stdio.h>#include<string.h>#include<stack>using namespace std ;int map[15][105] ; //15行105列,存储矩阵int dpm[105][15] ; //105行15列,存储对应的最小值int seq[105][15] ; //105行15列,存储序列bool judge(int x , int y , int len) ; //判断字典序大小int row ;int col ;int main(){//freopen("116.in" , "r" , stdin) ;//freopen("116.out" , "r" , stdout) ;while(cin>>row>>col){int i ;int j ;memset(map , 0 , sizeof(map)) ;memset(dpm , 0 , sizeof(dpm)) ;memset(seq , 0 , sizeof(seq)) ;for(i = 0 ; i < row ; i ++)for(j = 0 ; j < col ; j ++)cin>>map[i][j] ;for(i = 0 ; i < row ; i ++)dpm[0][i] = map[i][0] ;int k ;//主要的dp过程,尤其注意对字典序的判断for(i = 1 ; i < col ; i ++){for(j = 0 ; j < row ; j ++){k = (row + j - 1) % row ;dpm[i][j] = dpm[i-1][k] + map[j][i] ;seq[i][j] = k ;if(dpm[i][j] > dpm[i-1][j] + map[j][i]){dpm[i][j] = dpm[i-1][j] + map[j][i] ;seq[i][j] = j ;}else if(dpm[i][j] == dpm[i-1][j] + map[j][i] && judge(seq[i][j] , j , i - 1))seq[i][j] = j ;k = (j + 1)%row ;if(dpm[i][j] > dpm[i-1][k] + map[j][i]){dpm[i][j] = dpm[i-1][k] + map[j][i] ;seq[i][j] = k ;}else if(dpm[i][j] == dpm[i-1][k] + map[j][i] && judge(seq[i][j] , k , i - 1))seq[i][j] = k ;}}int nmin ;nmin = 0 ;for(i = 1 ; i < row ; i ++){if(dpm[col-1][i] < dpm[col-1][nmin])nmin = i ;else if(dpm[col-1][i] == dpm[col-1][nmin] && judge(nmin , i , col - 1))nmin = i ;}stack<int> a ;i = nmin ;j = col - 1  ;while(j > 0){i = seq[j][i] ;a.push(i) ;j -- ;}while(!a.empty()){cout<< a.top() + 1 <<" " ;a.pop() ;}cout<<nmin + 1<<endl ;cout<<dpm[col-1][nmin]<<endl ;}return 0 ;}//判断字典序bool judge(int x , int y , int len){int i ;int j ;stack<int> a ;stack<int> b ;//用栈缓存线路数据a.push(x) ;b.push(y) ;while(len > 0){x = seq[len][x] ;y = seq[len][y] ;a.push(x) ;b.push(y) ;len -- ;}while(!a.empty()){if(a.top() > b.top())return true ;else if(a.top() < b.top())return false ;a.pop() ;b.pop() ;}return false ;}


 这个题目当然还可以逆序动规,这样动规的时候可以很容易保证字典序,而不用编写专门的函数来验证字典序问题。代码如下:

/*ID: csuchenanprog: uva 116 - Unidirectional TSPLANG: C++*/#include<iostream>#include<stdio.h>#include<string.h>using namespace std ;const int maxn = 105 ;int map[15][maxn] ;int dpm[15][maxn] ;int seq[15][maxn] ;int row ;int col ;int main(){//freopen("116.in" , "r" , stdin) ;//freopen("116.out" , "w" , stdout) ;while(cin>>row>>col){int i ;int j ;int k ;memset(map , 0 , sizeof(map)) ;memset(dpm , 0 , sizeof(dpm)) ;memset(seq , 0 , sizeof(seq)) ;for(i = 0 ; i < row ; i ++)for(j = 0 ; j < col ; j ++)cin>>map[i][j] ;for(j = 0 ; j < row ; j ++)dpm[j][col-1] = map[j][col-1] ;for(i = col - 2 ; i >= 0 ; i --){for(j = 0 ; j <= row ; j ++){//ÓÒÉÏk = (j - 1 + row) % row ;dpm[j][i] = dpm[k][i+1] + map[j][i] ;seq[j][i] = k ;//ÓÒ²àif(dpm[j][i] > dpm[j][i+1] + map[j][i] ){dpm[j][i] = dpm[j][i+1] + map[j][i] ;seq[j][i] = j ;}else if(dpm[j][i] == dpm[j][i+1] + map[j][i] && seq[j][i] > j){seq[j][i] = j ;}//ÓÒϲàk = (j + 1) % row ;if(dpm[j][i] > dpm[k][i+1] + map[j][i] ){dpm[j][i] = dpm[k][i+1] + map[j][i] ;seq[j][i] = k ;}else if(dpm[j][i] == dpm[k][i+1] + map[j][i] && seq[j][i] > k){seq[j][i] = k ;}}}int nmin ;nmin = 0 ;for(i = 1 ; i < row ; i ++){if(dpm[i][0] < dpm[nmin][0])nmin = i ;else if(dpm[i][0] == dpm[nmin][0] && nmin > i)nmin = i ;}j = 0 ;i = nmin ;while(j < col - 1){cout<<i + 1<<" " ;i = seq[i][j] ;j ++ ;}cout<<i + 1 <<endl ;cout<<dpm[nmin][0]<<endl ;}return 0 ;}


 

 

原创粉丝点击