hdu3001Travelling (状态压缩DP,三进制)

Travelling

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

Total Submission(s): 3611 Accepted Submission(s): 1132

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

由于本题中一个点最多能够访问2次,由此可以联想到3进制;

dp[j][i]表示在状态i下到达终点j走过的最小的路程。具体下面的代码中有解释。

#include<stdio.h>
int map[12][12],n,dp[12][60000];//dp[i][state]表示state状态以i点结尾的最小路径
int Min(int a,int b)
{
    return a>b?b:a;
}
int toArray(int three[],int sum)
{
    int k=0;
    for(int i=0;i<n;i++)
    {
        three[i]=sum%3; sum/=3; if(three[i])k++;
    }
    return k;//在状态sum中有k个点己经走过
}
int main()
{
    int m,a,b,c,in[12],MIN,three[12],k;
    in[0]=1;
    for(int i=1;i<=10;i++)in[i]=in[i-1]*3; //3的i次方
    while(scanf("%d%d",&n,&m)==2)
    {
        for(int i=0;i<n;i++)//初始化
        {
            for(int j=0;j<in[n];j++)
                dp[i][j]=-1;
            for(int j=0;j<n;j++)
            map[i][j]=-1;
        }
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c); a--; b--;
            if(map[a][b]!=-1)//判重
            map[a][b]=map[b][a]=Min(map[a][b],c);
            else
            map[a][b]=map[b][a]=c;
        }
        MIN=-1;
        for(int Go=1;Go<in[n];Go++)//枚举己走的状态Go
        {
           k=toArray(three,Go);
           for(int i=0;i<n;i++)
           if(three[i])//状态Go以点i结尾时
           {
                if(k==1)//只有一个点
                    dp[i][Go]=0;

                if(dp[i][Go]==-1)continue;//状态Go不能以点i为结尾点
                if(k==n)//n个点己经走过
                {
                    if(MIN==-1)MIN=dp[i][Go];
                    else  MIN=Min(MIN,dp[i][Go]);
                }
                for(int j=0;j<n;j++)//找个点j,从i点走到j点,状态tGo以j点结尾
                if(i!=j&&three[j]<2&&map[i][j]!=-1)
                {
                    int tGo=Go+in[j];
                    if(dp[j][tGo]==-1)
                        dp[j][tGo]=dp[i][Go]+map[i][j];
                    else
                        dp[j][tGo]=Min(dp[i][Go]+map[i][j],dp[j][tGo]);
                }
           }
        }

        printf("%d\n",MIN);
    }
}

hdu3001Travelling (状态压缩DP,三进制),布布扣,bubuko.com

时间: 2024-12-20 11:56:16

hdu3001Travelling (状态压缩DP,三进制)的相关文章

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题目大意:有n个城市,m条路,每条路都有一定的花费,可以从任意城市出发,每个城市不能经过两次以上,要求经过所有城市并且花费最少,求出最小花费. 解题思路:三进制的状态压缩DP,跟二进制还是有一点不一样的,因为三进制没有直接的位运算,还要自己先做处理利用num[i][j]记录数字i各位的三进制表示方便计算,其他的就跟二进制状态压缩没有太大区别了.还有注意: ①开始要将n个起点初始化,dp[bit

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

题意:有 n 个city,可以选择任一城市作为起点,每个城市不能访问超过2次, 城市之间有权值,问访问全部n个城市需要的最小权值. 思路:因为每个城市可以访问最多两次,所以用三进制表示访问的状态. 详细见代码注释!!!! #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #include<cmath> #inclu

2010辽宁省赛E(Bellman_Ford最短路,状态压缩DP【三进制】)

#include<bits/stdc++.h>using namespace std;const int inf=0x3f3f3f3f;struct node{    int v,z,d,next;//存可以连接的点,用next存邻接表}a[10010];struct road{    int u,cnt,dis;//dis储存当前需要的钱数,即最短路算法里的权,u储存顶点,cnt储存组合数即状态压缩dp    road(int uu,int cntt,int diss)    {      

HDU 3001【状态压缩DP】

题意: 给n个点m条无向边. 要求每个点最多走两次,要访问所有的点给出要求路线中边的权值总和最小. 思路: 三进制状态压缩DP,0代表走了0次,1,2类推. 第一次弄三进制状态压缩DP,感觉重点是对数据的预处理,利用数组分解各个位数,从而达到类似二进制的目的. 然后就是状态的表示,dp[s][i]表示状态s时到达i的最优值. 状态转移也一目了然,不废话. #include<stdio.h> #include<string.h> #include<algorithm> u

hdu4628(状态压缩DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4628 一道典型的状态压缩DP...也是想了好久又经过大神的提示才想出来的,马上要比赛了,然后又遇到点了情感方面的问题...真是作死的节奏...悲催的程序员命...不多说了,看题... Pieces Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission

hdu 3217 Health(状态压缩DP)

Health Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 527    Accepted Submission(s): 145 Problem Description Unfortunately YY gets ill, but he does not want to go to hospital. His girlfriend LM

POJ 1038 Bugs Integrated, Inc. 状态压缩DP

题目来源:1038 Bugs Integrated, Inc. 题意:最多能放多少个2*3的矩形 思路:状态压缩DP啊 初学 看着大牛的代码搞下来的  总算搞懂了 接下来会更轻松吧 3进制代表前2行的状态(i行和i-1行)1代表i-1行占位 2代表i行占位 i-1不管有没有占位都不会影响的0代表i行和i-1行都空闲 然后枚举状态dfs更新状态 话说就不能没写深搜了 有点不会了 #include <cstdio> #include <cstring> #include <alg

bzoj1725: [Usaco2006 Nov]Corn Fields牧场的安排(状态压缩DP)

本来就是一个写不大来动态规划的人,结果现在又了解到还有种东西叫状态压缩dp,唉... 找了一道例题来试试看:http://www.lydsy.com/JudgeOnline/problem.php?id=1725 解:我们用f[i][j]来表示当前第i行,状态为j的情况下,(且之前的1~i-1的方案数已经确定了),前i行有多少种方案,那么动态转移方程其实很明显: f[i][j]=sum(f[i-1][k]);(当上一行为第k种状态且与当前枚举的第i种状态不会产生相邻的土地,就加上f[i-1][k

LightOJ1364---Expected Cards(概率dp+三进制状压)

Taha has got a standard deck of cards with him. In addition to the 52 regular ones, there are 2 joker cards. Every regular card has a rank and a suit. The ranks in ascending order are: A, 2, 3, 4, 5, 6, 7, 8, 9, T, J, Q and K. The suit of a card can