HDU 3001 Travelling (状压DP + BFS)

Posted dwtfukgv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3001 Travelling (状压DP + BFS)相关的知识,希望对你有一定的参考价值。

题意:有一个人要去旅游,他想要逛遍所有的城市,但是同一个城市又不想逛超过2次。现在给出城市之间的来往路费,他可以选择任意一个点为起点。

问逛遍所有城市的最低路费是多少。

析:用三进制表示每个城市的访问次数,然后 bfs 进行遍历,不过要注意这个题卡内存,必须要去年一些无用的状态,要不然会超内存的,还不能枚举每个城市,

这样可能会超时的,可以直接把所有的城市放进去,直接进行遍历。一个比较经典的题目。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e16;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 10 + 5;
const int mod = 100000000;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c){
  return r >= 0 && r < n && c >= 0 && c < m;
}

int G[10][10];
int dp[60000][10];
int f[10];

struct Node{
  int state, pos;
  Node(int s, int p) : state(s), pos(p) { }
};

int calc(int state, int i){
  return state + f[i];
}

bool judge(int state){
  for(int i = 0; i < n; ++i, state /= 3)
    if(state % 3 == 0)  return false;
  return true;
}

int bfs(){
  memset(dp, INF, sizeof dp);
  queue<Node> q;
  for(int i = 0; i < n; ++i){
    dp[calc(0, i)][i] = 0;
    q.push(Node(calc(0, i), i));
  }
  int ans = INF;
  if(n == 1)  return 0;

  while(!q.empty()){
    Node u = q.front();  q.pop();
    int state = u.state;
    for(int i = 0; i < n; ++i)  if(G[u.pos][i] != INF){
      if(state / f[i] % 3 == 2)  continue;
      int newstate = calc(state, i);
      int neww = dp[state][u.pos] + G[u.pos][i];
      if(dp[newstate][i] <= neww)  continue;  //去年无用的状态,要不然可能会超时或者超内存
      dp[newstate][i] = neww;
      if(judge(newstate)){
        ans = min(ans, dp[newstate][i]);
        continue;
      }
      else q.push(Node(newstate, i));
    }
  }
  return ans;
}

int main(){
  f[0] = 1;
  for(int i = 1; i < 10; ++i)  f[i] = f[i-1] * 3;
  while(scanf("%d %d", &n, &m) == 2){
    memset(G, INF, sizeof G);
    for(int i = 0; i < m; ++i){
      int a, b, c;
      scanf("%d %d %d", &a, &b, &c);
      --a, --b;
      G[a][b] = G[b][a] = min(G[a][b], c);
    }
    int ans = bfs();
    printf("%d\n", ans == INF ? -1 : ans);
  }
  return 0;
}

  

以上是关于HDU 3001 Travelling (状压DP + BFS)的主要内容,如果未能解决你的问题,请参考以下文章

hdu 3001 Travelling (三进制)状压dp

HDU 3001 Travelling (状压DP + BFS)

hdu 3001 Travelling 经过所有点(最多两次)的最短路径 三进制状压dp

HDU 3001 Travelling(状态压缩DP+三进制)

HDU3001(状压DP,三进制)

HDU 3001 三进制状压DP