状压DP [HDU 3001] Travelling

Travelling

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 4166    Accepted Submission(s): 1339

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

2009 Multi-University Training Contest 11 - Host by HRBEU

状压dp、仔细想一下

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f

int n,m;
int s[12];
int mpt[12][12];
int tr[12][60000];
int dp[12][60000];

void init()                               //预处理s和tr数组
{
    int i,j,t;
    s[0]=1;
    for(i=1;i<=10;i++)
    {
        s[i]=3*s[i-1];
    }
    for(j=0;j<s[10];j++)
    {
        t=j;
        for(i=0;i<10;i++)
        {
            tr[i][j]=t%3;
            t/=3;
        }
    }
}
void solve()
{
    int i,j,k,MAX=s[n];
    for(i=0;i<n;i++)
    {
        dp[i][s[i]]=0;
    }

    for(j=0;j<MAX;j++)
    {
        for(i=0;i<n;i++)
        {
            if(tr[i][j]==0) continue;
            for(k=0;k<n;k++)
            {
                if(i==k) continue;
                if(tr[k][j]==0) continue;
                int prej=j-s[i];
                dp[i][j]=min(dp[i][j],dp[k][prej]+mpt[k][i]);
            }
        }
    }

    int ans=INF;
    for(i=0;i<n;i++)
    {
        for(j=0;j<s[n];j++)
        {
            for(k=0;k<n;k++)
            {
                if(tr[k][j]==0) break;
            }
            if(k==n)
                ans=min(ans,dp[i][j]);
        }
    }

    if(ans==INF)
        puts("-1");
    else
        printf("%d\n",ans);
}
int main ()
{
    init();
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(dp,INF,sizeof(dp));
        memset(mpt,INF,sizeof(mpt));
        while(m--)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            a--;
            b--;
            if(c<mpt[a][b])
            {
                mpt[a][b]=c;
                mpt[b][a]=c;
            }
        }
        solve();
    }
    return 0;
}
时间: 2024-08-10 00:07:28

状压DP [HDU 3001] Travelling的相关文章

状压DP [HDU 1074] Doing Homework

Doing Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5472    Accepted Submission(s): 2311 Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lo

[AC自动机+spfa+状压dp] hdu 3247 Resource Archiver

题意: 给n个本源串,m个病毒串 求一个最多的长度的单词包含所有的本源串并不包含任意一个病毒串 串均为01串 思路: 只有10个本源串 一开始想的是直接建立完trie图 然后在图上直接spfa 结果发现 dis[60005][1030] 超内存了 这个时候就要想到 其实只有节点的mark值大于0的节点是我们需要用的 就是那些含有状压权值的节点 那么我们先记录下这些节点是哪些 然后发现其实这些不到100个节点 所以跑100遍spfa 求出两两之间的最短路 然后用这个距离 去状压dp 数组就成了 d

[AC自动机+状压dp] hdu 4534 郑厂长系列故事——新闻净化

题意:中文的题目,意思就是说有很多串,每个串都有权值,权值为999的串必须出现,-999的串必须不出现.权值在-999~999之间. 然后必须出现的串不超过8个.然后给一个全为小写目标串,问最少需要删除多少个字母才能够保证必须出现的串都出现,次数一样保证权值最大.输出次数和权值. 然后根据样例,那些必须出现的串,其实权值是0. 思路: 很明显一开始建自动机构成trie图,但是需要注意的就是mark和sum的更新.个人是把所有中间的节点的sum全部赋值成了-inf. 接着只有8个必须出现的串,所以

[AC自动机+状压dp] hdu 2825 Wireless Password

题意: 给n,m,k ,再给出m个单词 问长度为n的字符串,至少在m个单词中含有k个的组成方案有多少种. 思路: 由于m最大是10,所以可以采取状压的思想 首先建立trie图,在每个单词的结束节点标记一个mark=(1<<id),id为单词的编号 然后需要注意的,对于每个节点,应该顺着fail指针遍历一遍, 把所有的mark取一个并集. 因为就是如果单词出现包含的话,比如 she和he 我拿了she,其实等于两个都拿了. dp[i][j][k]  i步在节点j状态k的方案数 然后就是一个四重循

[状压dp] hdu 4064 Carcassonne

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4064 Carcassonne Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 857    Accepted Submission(s): 326 Problem Description Carcassonne is a tile-bas

[状压dp] hdu 4628 Pieces

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4628 Pieces Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1665    Accepted Submission(s): 862 Problem Description You heart broke into pieces

HDU 3001 Travelling 状压DP

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题意:还是环游地图的问题,只不过这回旅行者对自己有着严格的要求,地图上每个点的经过次数不能超过两次. 思路:依然是状压DP问题,根上一道很像,只不过这次对于每个点来说有三种状态,分别是未经过,经过一次,经过两次.所以要用三进制的数来进行状态压缩,这个关键点想明白了其他的和上一道基本一样了.对于我来说需要注意的是:能够到达某一个点经过了两次的状态的前一个状态是这个点已经经过了一次的状态,而不是从来未

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

题意: 给出n<=10个点,有m条边的无向图.问:可以从任意点出发,至多经过同一个点2次,遍历所有点的最小费用? 思路: 本题就是要卡你的内存,由于至多可经过同一个点2次,所以只能用3进制来表示,3进制可以先将表打出来.在走的时候注意只能走2次,其他的和普通的TSP状压DP是一样的.注意点:重边,自环等等,老梗了. 1 //#include <bits/stdc++.h> 2 #include <iostream> 3 #include <cstdio> 4 #i

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

题目链接 题意 给定一个\(N\)个点的无向图,求从任意一个点出发,经过所有点的最短路径长度(每个点至多可以经过两次). 思路 状态表示.转移及大体思路 与 poj 3311 Hie with the Pie 经过所有点(可重)的最短路径 floyd + 状压dp 相同. 但,因为是每个点 至多可以经过两次,所以应该用 三进制 来表示状态. 因为三进制不能直接通过移位来表示,所以要 预处理 出每个数字\(state\)的三进制表示中每一位\(i\)上的值\(dig[state][i]\). 注意