HDU 3001 Travelling(DP状态压缩)

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 

题意:每个城市游览次数d>=1&&d<=2问最小花费。

三进制状态转移:dp[status+num[j]][j]=min(dp[status+num[j]][j],dp[status][i]+dis[i][j]);
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<limits.h>
typedef long long LL;
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f;
int dp[60000][11];//记录i状态下以j为终点的值
int f[60000][11];//记录i状态下j点的访问次数
int num[12];
int dis[15][15];
int n,m;

void init()
{
    num[1]=1;
    REPF(i,2,11)
        num[i]=num[i-1]*3;
    for(int i=0;i<num[11];i++)
    {
        int temp=i;
        REPF(j,1,10)
        {
            f[i][j]=temp%3;
            temp/=3;
        }
    }
//    for(int i=1;i<=10;i++)
//       cout<<"2333  "<<f[12][i]<<endl;
}
int main()
{
    int x,y,val;
    init();
    while(~scanf("%d%d",&n,&m))
    {
        CLEAR(dp,INF);
        CLEAR(dis,INF);
//        cout<<"23333 "<<INF<<endl;
        while(m--)
        {
            scanf("%d%d%d",&x,&y,&val);
            if(dis[x][y]>val) dis[x][y]=dis[y][x]=val;
        }
        REPF(i,1,n)
           dp[num[i]][i]=0;
//        cout<<"2333  "<<dp[3][2]<<" "<<dp[2][3]<<endl;
        int ans=INF;
        for(int status=1;status<num[n+1];status++)
        {
            int ok=1;
            REPF(i,1,n)
            {
                if(f[status][i]==0)//在状态status下的i次数为0,ok=0,还有地方没有游
                    ok=0;
                if(dp[status][i]==INF)//不存在这条道路
                    continue;
                REPF(j,1,n)
                {
                    if(i==j)  continue;
                    if(f[status][j]==2)  continue;//状态status下j点走过两次
                    if(dis[i][j]==INF)  continue;
                    dp[status+num[j]][j]=min(dp[status+num[j]][j],dp[status][i]+dis[i][j]);//状态转移
                }
            }
            if(ok)
            {
                REPF(i,1,n)
                   ans=min(ans,dp[status][i]);
            }
        }
        if(ans==INF)   ans=-1;
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-17 02:16:41

HDU 3001 Travelling(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 (bfs+状态压缩)

Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3905    Accepted Submission(s): 1234 Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is

HDU - 3001 Travelling (状态压缩)

题目大意:有一个人要去旅游,他想要逛遍所有的城市,但是同一个城市又不想逛超过2次.现在给出城市之间的来往路费,他可以选择任意一个点为起点.问逛遍所有城市的最低路费是多少 解题思路:这题和POJ - 3311 Hie with the Pie相似 这里的状态标记要用三进制数来表示,就可以表示每个城市去过的次数了 设dp[i][state]为现在在i城市,逛过的城市状态为state的最低路费 状态转移方程: dp[i][S + i城市标记] = min(dp[i][S + i城市标记], dp[j]

hdu 4352 数位dp + 状态压缩

XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2265    Accepted Submission(s): 927 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then careful

HDU 4842--过河(dp+状态压缩)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4842 过河 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Problem Description 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的

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

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

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

【HDU 4352】 XHXJ&#39;s LIS (数位DP+状态压缩+LIS)

XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2422    Accepted Submission(s): 990 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then careful

[数位dp+状态压缩] hdu 4352 XHXJ&#39;s LIS

题意: 给x.y.k,在[x,y] 范围内最长上升子序列长度是k的数有几个 思路: 模仿 LIS nlogn的想法,这里就只有10个数,进行状压 然后直接搜就好了不用二分 然后按位dp下去就ok了! 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"al