[hdu3001]Travelling

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7817    Accepted Submission(s):
2553

Problem Description
After coding so many days,Mr Acmer wants to have a good
rest.So travelling is the best choice!He has decided to visit n cities(he
insists on seeing all the cities!And he does not mind which city being his start
station because superman can bring him to any city at first but only once.), and
of course there are m roads here,following a fee as usual.But Mr Acmer gets
bored so easily that he doesn't want to visit a city more than twice!And he is
so mean that he wants to minimize the total fee!He is lazy you see.So he turns
to you for help.
 
Input
There are several test cases,the first line is two
intergers n(1<=n<=10) and m,which means he needs to visit n cities and
there are m roads he can choose,then m lines follow,each line will include three
intergers a,b and c(1<=a,b<=n),means there is a road between a and b and
the cost is of course c.Input to the End Of File.
 
Output
Output the minimum fee that he should pay,or -1 if he
can't find such a route.
 
Sample Input

2 1
1 2 100
3 2
1 2 40
2 3 50
3 3
1 2 3
1 3 4
2 3 10

 
Sample Output

100
90
7

 
Source
 
Recommend
gaojie
 
题目大意:有N个点,M条边,每条边都有权值,每个点不能经过大于两次,问把整个图走完的最小代价。如果不行输出-1。
试题分析:这题不同于codevs上那道3分钟的TSP水题,这回对于次数有限制。
     考虑2进制,我们发现无法表示它的状态了,那么3进制可行么?
     3进制每位代表访问过这个节点的次数。dp[S][j]表示状态为S,现在在j的最小代价。
     那么dp[S][j]=min(dp[S][j],dp[S-tri[j]][k]+e[k][j]);
     tri[i]表示三进制下长度为i的MAX。
     我们可以先预处理出来3进制每个数每位是什么,然后就好做了。
 
代码(为什么就我写的是逆推QAQ):
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std; inline int read(){
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int MAXN=100001;
const int INF=0x1f1f1f1f;//这里不知道为什么赋值9999999过不了
const int Max3=59050;
int tri[12] ={0,1,3,9,27,81,243,729,2187,6561,19683,59049};
int N,M;
int ditk[100001][11];
int dp[100001][11];
int e[11][11]; int ans; int main(){
memset(ditk,0,sizeof(ditk));
for(int i=1;i<Max3;i++){
int tmp=0,x=i;
while(x){
ditk[i][++tmp]=x%3;
x/=3;
if(x==0) break;
}
}
while(scanf("%d%d",&N,&M)!=EOF){
ans=INF;
memset(dp,INF,sizeof(dp));
memset(e,INF,sizeof(e));
for(int i=1;i<=M;i++){
int u=read(),v=read(),w=read();
e[u][v]=e[v][u]=min(w,e[v][u]);
}
for(int i=1;i<=N;i++) dp[tri[i]][i]=0;
for(int i=1;i<tri[N+1];i++){
bool k=true;
for(int j=1;j<=N;j++){
if(!dp[i][j]) continue;
if(!ditk[i][j]) continue;
for(int k=1;k<=N;k++){
if(e[k][j]>=INF||ditk[i-tri[j]][j]>=2||k==j||!ditk[i-tri[j]][k]) continue;
dp[i][j]=min(dp[i][j],dp[i-tri[j]][k]+e[k][j]);
}
}
}
for(int i=1;i<tri[N+1];i++){
bool k=true;
for(int j=1;j<=N;j++) if(!ditk[i][j]){
k=false; break;
}
if(k) for(int j=1;j<=N;j++) ans=min(ans,dp[i][j]);
}
if(ans!=INF) printf("%d\n",ans);
else puts("-1");
}
}

又写了一个顺推:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std; inline int read(){
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int MAXN=100001;
const int INF=0x1f1f1f1f;
const int Max3=59050;
int tri[12] ={0,1,3,9,27,81,243,729,2187,6561,19683,59049};
int N,M;
int ditk[100001][11];
int dp[100001][11];
int e[11][11]; int main(){
memset(ditk,0,sizeof(ditk));
for(int i=0;i<Max3;i++){
int tmp=0,x=i;
while(x){
ditk[i][++tmp]=x%3;
x/=3;
if(x==0) break;
}
}
while(scanf("%d%d",&N,&M)!=EOF){
int ans=INF;
memset(dp,INF,sizeof(dp));
memset(e,INF,sizeof(e));
for(int i=1;i<=M;i++){
int u=read(),v=read(),w=read();
if(w<e[u][v]) e[u][v]=e[v][u]=w;
}
for(int i=1;i<=N;i++) dp[tri[i]][i]=0;
for(int i=0;i<tri[N+1];i++){
bool flagt=true;
for(int j=1;j<=N;j++){
if(!ditk[i][j]) flagt=false;
if(dp[i][j]==INF) continue;
for(int k=1;k<=N;k++){
if(k==j) continue;
if(e[j][k]>=INF||ditk[i][k]>=2) continue;
dp[i+tri[k]][k]=min(dp[i+tri[k]][k],dp[i][j]+e[j][k]);
}
}
if(flagt){
for(int j=1;j<=N;j++)
ans=min(ans,dp[i][j]);
}
}
if(ans==INF) puts("-1");
else printf("%d\n",ans);
}
}

【状压dp】Travelling的更多相关文章

  1. Travelling(HDU3001+状压dp+三进制+最短路)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题目: 题意:n个城市,m条边,每条边都有一个权值,问你经过所有的城市且每条边通过次数不超过两次 ...

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

    题目链接 题意 给定一个\(N\)个点的无向图,求从任意一个点出发,经过所有点的最短路径长度(每个点至多可以经过两次). 思路 状态表示.转移及大体思路 与 poj 3311 Hie with the ...

  3. HDU 3001 Travelling (状压DP,3进制)

    题意: 给出n<=10个点,有m条边的无向图.问:可以从任意点出发,至多经过同一个点2次,遍历所有点的最小费用? 思路: 本题就是要卡你的内存,由于至多可经过同一个点2次,所以只能用3进制来表示 ...

  4. HDU 3001 Travelling ——状压DP

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

  5. HDU-4856 Tunnels (BFS+状压DP)

    Problem Description Bob is travelling in Xi’an. He finds many secret tunnels beneath the city. In hi ...

  6. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  7. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  8. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  9. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

  10. 【BZOJ2073】[POI2004]PRZ 状压DP

    [BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...

随机推荐

  1. Linux while 和 read 的用法

    Reference: [ linux man doc ] [ CSDN roler_ ] [ Reads from the file descriptor] read 命令说明 SYNTAX : re ...

  2. python中正则用法举例

    一.根据正则表达式替换字符串 import re text='abc123' text=re.sub(r'\d','-',text) print(text) 输出:abc---将每个数字替换为-,如果 ...

  3. [Leetcode Week15]Populating Next Right Pointers in Each Node

    Populating Next Right Pointers in Each Node 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/populati ...

  4. js中常用的数组方法

    在数组的尾部增加或删除某个元素:push() 和 pop() push() : 在数组的尾部追加一个或多个元素,并返回数组的长度 pop():在数组的尾部删除一个元素,并返回被删除项 var arr ...

  5. FineReport——JS二次开发(复选框全选)

    在进行查询结果选择的时候,我们经常会用到复选框控件,对于如何实现复选框全选,基本思路: 在复选框中的初始化事件中把控件加入到一个全局数组里,然后在全选复选框里对数组里的控件进行遍历赋值. 首先,定义两 ...

  6. CodeForces 450B

    B. Jzzhu and Sequences time limit per test 1 second memory limit per test 256 megabytes input standa ...

  7. Django 项目CRM总结

    0. 项目说明: 1. 销售自动分配客户资源: 给销售分配权重及承单数量,创建权重表,通过销售权重进行从大到小进行排序 以承单数循环添加到列表,承单数是多少列表添加就添加多少次 考虑到如果服务重启,或 ...

  8. 深度学习方法:受限玻尔兹曼机RBM(一)基本概念

    欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术.应用感兴趣的同学加入. 最近在复习经典机器学习算法的同 ...

  9. hdu 3729(二分图最大匹配)

    I'm Telling the Truth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  10. hdu5823

    官方题解:直接状压dp就行了,f[S]表示点集S的色数,枚举子集转移(子集是独立集).这样是3^n的. 这样就可以过了……(独立集就是点互相没有连边) 学到了一个穷举子集的简便写法 for (int ...