题意:有一个人要去旅游,他想要逛遍所有的城市,但是同一个城市又不想逛超过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)的更多相关文章

  1. HDU 3001 Travelling ——状压DP

    [题目分析] 赤裸裸的状压DP. 每个点可以经过两次,问经过所有点的最短路径. 然后写了一发四进制(真是好写) 然后就MLE了. 懒得写hash了. 改成三进制,顺利A掉,时间垫底. [代码] #in ...

  2. HDU - 3001 Travelling 状压dp + 三进制 [kuangbin带你飞]专题二

    终于刷完搜索专题了. 题意:给定n个城市,每个城市参观不能超过两次,两个城市之间有道路通过需要花费X,求通过能所有城市的最小花费. 思路:每个城市有三个状态0,1,2,可用三进制存储所有城市的访问状态 ...

  3. hdu 3247 AC自动+状压dp+bfs处理

    Resource Archiver Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Ot ...

  4. BZOJ_3049_[Usaco2013 Jan]Island Travels _状压DP+BFS

    BZOJ_3049_[Usaco2013 Jan]Island Travels _状压DP+BFS Description Farmer John has taken the cows to a va ...

  5. HDU 3247 Resource Archiver(AC自动机 + 状压DP + bfs预处理)题解

    题意:目标串n( <= 10)个,病毒串m( < 1000)个,问包含所有目标串无病毒串的最小长度 思路:貌似是个简单的状压DP + AC自动机,但是发现dp[1 << n][ ...

  6. HDU 3681 Prison Break(状压DP + BFS)题解

    题意:一张图,F是起点,Y是必须要到的点,D不能走,G可以充电.可以往四个方向走,每走一步花费一个电,走到G可以选择充满电或者不充,每个G只能充一次.问你走遍Y的最小初始点亮.number(G) + ...

  7. HDU 4284Travel(状压DP)

    HDU 4284    Travel 有N个城市,M条边和H个这个人(PP)必须要去的城市,在每个城市里他都必须要“打工”,打工需要花费Di,可以挣到Ci,每条边有一个花费,现在求PP可不可以从起点1 ...

  8. HDU 4336 容斥原理 || 状压DP

    状压DP :F(S)=Sum*F(S)+p(x1)*F(S^(1<<x1))+p(x2)*F(S^(1<<x2))...+1; F(S)表示取状态为S的牌的期望次数,Sum表示 ...

  9. HDU3001 Travelling —— 状压DP(三进制)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3001 Travelling Time Limit: 6000/3000 MS (Java/ ...

随机推荐

  1. mysql 在Windows下自动备份

    1.一般备份方法主要为两种: 直接保存数据库data文件夹 mysqldump 用sql命令备份(文件存放目录必须存在) 首先cmd进入MySQL\bin,然后mysqldump --default- ...

  2. asp.net core mcroservices 架构之 分布式日志(二)之自定义日志开发

    netcore日志原理 netcore的日志是作为一个扩展库存在的,每个组件都有它的入口,那么作为研究这个组件的入口是最好的,首先看两种方式: 这个是源码例子提供的. var loggingConfi ...

  3. CF 19E Fairy——树上差分

    题目:http://codeforces.com/contest/19/problem/E 去掉一条边,使无向图变成二分图. 该边应该被所有奇环经过,且不被偶环经过. 因为一条非树边一定只在一个环里. ...

  4. ABP 学习系列 - 目录

    一.ABP 学习系列 - 入门介绍之单表 http://www.cnblogs.com/yabu007/p/8067694.html 二.ABP 学习系列 - 入门介绍之多表 http://www.c ...

  5. 在Mac系统下如何恢复SourceTree全局忽略的文件

    在家目录“~”下编辑 “.gitignore_global ” 文件即可:vim  .gitignore_global

  6. 编译PHP扩展的通用方法

    以安装swoole扩展为例: 步骤1: wget  pecl.php.net/get/swoole-1.7.21.tgz  (下载swoole打包文件) 步骤2: tar zxvf swoole-1. ...

  7. hihoCoder#1079(线段树+坐标离散化)

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~ 这天小Hi和小Ho所在的学 ...

  8. declare handler 声明异常处理的语法

    声明异常处理的语法 DECLARE {EXIT | CONTINUE} HANDLER FOR {error-number | SQLSTATE error-string | condition} S ...

  9. windows中git输错密码后不能重新输入的问题

    当输入密码错误后,git会把密码保存在windows的你的当前用户名的缓存中. 我们可以在控制面板中寻找到这个缓存,再删掉就可以了. 首先,打开“控制面板”,把“查看方式”改为“大图标”,再打开“用户 ...

  10. 问题:sqlserver 跨服务器连接;结果:Sql Server 跨服务器连接

    Sql Server 跨服务器连接 用openrowset连接远程SQL或插入数据 --如果只是临时访问,可以直接用openrowset --查询示例 select * from openrowset ...