HDU 3001 Travelling ( 状态压缩 )

来源:互联网 发布:淘宝龙瞎多少钱 编辑:程序博客网 时间:2024/06/05 19:51

题目链接~~>

做题感悟:以前也做过类似的题目,但是这里规定每个地点只能访问 2 次 ,用二进制结果超内存,然后就百度了一下原来用三进制。

解题思路:

                大体的思路还是和 TSP 差不多,只是这里一个地点可以最多拜访两次 ,用三进制就可以解决这个问题,但是三进制不如二进制好处理。因为每个地点最多可以拜访两次,so ~> 不可以用Floyd 预处理。先预处理出来三进制的各个状态,以及各个状态的各位的状态。dp[ S ] [ i ] 代表达到状态 S 后到达 i 最小花费。

             动态方程: dp [ S + t [ j ] ] [ j ] = min (dp [ S +  t [ j ] ] [  j  ] , dp[ S ]  + d [ i ] [ j  ] )  ;  

代码:

#include<iostream>#include<fstream>#include<iomanip>#include<ctime>#include<fstream>#include<sstream>#include<stack>#include<cstring>#include<cmath>#include<map>#include<queue>#include<vector>#include<cstdio>#include<algorithm>#define INT __int64using namespace std ;const double esp = 0.00000001 ;const int INF = 0x3f3f3f3f ;const int mod = 1e9 + 7 ;const int MY = 10 + 10 ;const int MX = 59049+ 10 ;int n ,m ;int t[MY] ,dp[MX][MY] ,d[MY][MY] ,f[MX][MY] ;void init() // 预处理状态{    t[0] = 1 ;    for(int i = 1 ;i <= 11 ; ++i)        t[i] = t[i-1] * 3 ;    for(int S = 0 ; S <= 59049 ; ++S)    {        int temp = S ,i = 0 ;        while(temp)        {            f[S][i++] = temp % 3 ;            temp /= 3 ;        }    }}void input(){   int u ,v ,w ;   memset(d ,INF ,sizeof(d)) ;   for(int i = 0 ;i < m ; ++i)   {       scanf("%d%d%d" ,&u ,&v ,&w) ;       u-- ; v-- ;       d[u][v] = d[v][u] = min(d[u][v] ,w) ;   }}void DP(){    int best = INF ;    memset(dp ,INF ,sizeof(dp)) ;    for(int i = 0 ;i < n ; ++i)       dp[t[i]][i] = 0 ;    for(int S = 0 ;S < t[n] ; ++S)    {        bool flag = true ; // 查看是否每个地点都拜访过了        for(int i = 0 ;i < n ; ++i)        {          if(dp[S][i] != INF)          {            for(int j = 0 ;j < n ; ++j)              if(i != j && f[S][j] <= 1 && d[i][j] != INF)              {                  int& ans = dp[S+t[j]][j] ;                  ans = min(ans ,dp[S][i] + d[i][j]) ;              }           }           if(!f[S][i]) flag = false ;          }          if(flag)                 for(int i = 0 ;i < n ; ++i)                     best = min(best ,dp[S][i]) ;    }    if(best != INF)              cout<<best<<endl ;    else      cout<<"-1"<<endl ;}int main(){    init() ;    while(~scanf("%d%d" ,&n ,&m))    {        input() ;        DP() ;    }    return 0 ;}



0 0
原创粉丝点击