HDU 4568 Hunter 最短路+状压DP

题意:给一个n*m的格子,格子中有一些数,如果是正整数则为到此格子的花费,如果为-1表示此格子不可到,现在给k个宝藏的地点(k<=13),求一个人从边界外一点进入整个棋盘,然后拿走所有能拿走的宝藏的最小花费,如果一次不能拿走所有能拿到的或者根本拿不到任何宝藏,输出0.

解法:看到k的范围应该想到状态压缩,将每个格子都看成一个点,再新建两个点,一个表示边界外的起点,用0表示,一个表示边界外的终点,用n*m+1表示,然后相互建边,建有向边,边权为终点格子的花费值,(其实都不用建边,直接跑最短路也行)然后求这k+2个点两两之间的最短距离,然后就化成TSP问题了,用状压DP可以解决。

求k+2个点两两之间的最短距离可以跑k+2次SPFA求出,复杂度不高。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define Mod 1000000007
using namespace std;
#define N 10007

int mp[304][304];
int C[304][304];
int dis[20][20];
int n,m,k;
int d[50005];
struct node
{
    int v,w,next;
}G[4*50005];
int head[4*50005],tot;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
int vis[50006];
struct Point
{
    int x,y;
}P[15];

int OK(int nx,int ny)
{
    if(nx >= 1 && nx <= n && ny >= 1 && ny <= m)
        return 1;
    return 0;
}

void addedge(int u,int v,int w)
{
    G[tot].v = v;
    G[tot].w = w;
    G[tot].next = head[u];
    head[u] = tot++;
}

void SPFA(int s)
{
    queue<int> que;
    while(!que.empty())
        que.pop();
    memset(vis,0,sizeof(vis));
    vis[s] = 1;
    que.push(s);
    for(int i=0;i<=n*m+1;i++)
        d[i] = Mod;
    d[s] = 0;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for(int i=head[u];i!=-1;i=G[i].next)
        {
            int v = G[i].v;
            int w = G[i].w;
            if(d[v] > d[u] + w)
            {
                d[v] = d[u] + w;
                if(!vis[v])
                {
                    vis[v] = 1;
                    que.push(v);
                }
            }
        }
    }
}

int dp[1<<17][20];

int main()
{
    int i,j;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
            {
                scanf("%d",&C[i][j]);
                if(C[i][j] == -1)
                    C[i][j] = Mod;
            }
        memset(head,-1,sizeof(head));
        tot = 0;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                int now = (i-1)*m + j;
                for(int h=0;h<4;h++)
                {
                    int kx = i + dx[h];
                    int ky = j + dy[h];
                    if(!OK(kx,ky))
                        continue;
                    int tmp = (kx-1)*m + ky;
                    addedge(now,tmp,C[kx][ky]);
                }
                if(i == 1 || i == n || j == 1 || j == m)
                {
                    addedge(0,now,C[i][j]);
                    addedge(now,n*m+1,0);
                }
            }
        }
        scanf("%d",&k);
        P[0].x = 1, P[0].y = 0;
        P[k+1].x = n,P[k+1].y = m+1;
        for(i=1;i<=k;i++)
            scanf("%d%d",&P[i].x,&P[i].y),P[i].x++,P[i].y++;
        for(i=0;i<=k+1;i++)
        {
            int s = (P[i].x-1)*m + P[i].y;
            SPFA(s);
            for(j=0;j<=k+1;j++)
            {
                if(i == j) continue;
                int v = (P[j].x-1)*m + P[j].y;
                dis[i][j] = d[v];
            }
        }
        for(i=0;i<(1<<16);i++)
        {
            for(j=0;j<16;j++)
                dp[i][j]=Mod;
        }
        for(i=0;i<k;i++)
        {
            dp[1<<i][i+1]=dis[0][i+1];
        }
        for(i=0;i<(1<<k);i++)
        {
            for(int kk=0;kk<k;kk++)
            {
                if(!(i&(1<<kk)))continue;
                for(int j=0;j<k;j++)
                {
                    if(i&(1<<j)) continue;
                    dp[i+(1<<j)][j+1]=min(dp[i+(1<<j)][j+1],dp[i][kk+1]+dis[kk+1][j+1]);
                }
            }
        }
        int minn=Mod;
        for(i=1;i<=k;i++)
            minn=min(dp[(1<<k)-1][i]+dis[i][k+1],minn);
        if(minn == Mod)
            cout<<0<<endl;
        else
            cout<<minn<<endl;
    }
    return 0;
}

时间: 2024-10-17 12:15:34

HDU 4568 Hunter 最短路+状压DP的相关文章

hdu 4568 Hunter 最短路+dp

Hunter Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2014    Accepted Submission(s): 615 Problem Description One day, a hunter named James went to a mysterious area to find the treasures. Jame

HDU 4856 Tunnels (最短路+状压DP)

题意:给你N*N的网格,'.'表示可以走,'#'表示不能走,m条管道,每条管道有起点和终点坐标, Bob每次可以走到相邻的网格花费1s,问Bob走完m条管道要花多少时间:Bob在管道内不计算时间 即计算Bob从管道 i 的出口走到管道 j 的入口的时间Dis(e[i],s[j])的最小和,起点可以任意: 思路:看了题解说是状态压缩DP然后深入理解了下. 首先算出d[e[i]][s[j]]的最短距离,不能到达为-1: dp[i][j] : 表示以 j 为起点状态为 i 的最小值.其中 i 是用十进

HDU 4114 Disney&#39;s FastPass (状压DP)

题意:给定 n 个区域,然后给定两个区域经过的时间,然后你有 k 个景点,然后给定个每个景点的区域和有票没票的等待时间,从哪些区域能够得到票,问你从景点1开始,最后到景点1,而且要经过看完这k个景点. 析:一个状压DP,dp[s1][s2][i] 表示已经访问了 s1 中的景点,拥有 s2 的票,当前在 i 区域,然后两种转移一种是去下一个景点,另一种是去下一个区域拿票.当时输入,写错了,卡了好长时间.... 代码如下: #pragma comment(linker, "/STACK:10240

POJ 2411 &amp;&amp; HDU 1400 Mondriaan&#39;s Dream (状压dp 经典题)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12341   Accepted: 7204 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

HDU 4906 Our happy ending (状压DP)

HDU 4906 Our happy ending 题目链接 题意:给定n个数字,每个数字可以是0-l,要选其中一些数字,然后使得和为k,问方案 思路:状压dp,滚动数组,状态表示第i个数字,能组成的数字状态为s的状态,然后每次一个数字,循环枚举它要选取1 - min(l,k)的多少,然后进行状态转移 代码: #include <cstdio> #include <cstring> typedef long long ll; const int N = (1<<20)

HDU 4856 Tunnels(BFS+状压DP)

HDU 4856 Tunnels 题目链接 题意:给定一些管道,然后管道之间走是不用时间的,陆地上有障碍,陆地上走一步花费时间1,求遍历所有管道需要的最短时间,每个管道只能走一次 思路:先BFS预处理出两两管道的距离,然后状态压缩DP求解,dp[s][i]表示状态s,停在管道i时候的最小花费 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using

【BZOJ1097】[POI2007]旅游景点atr 最短路+状压DP

[BZOJ1097][POI2007]旅游景点atr Description FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD不希望在刚吃过一顿大餐之后立刻去下一个城市登山,而是希望去另外什么地方喝下午茶.幸运的是,FGD的旅程不是既定的,他可以在某些旅行方案之间进行选择.由于FGD非常讨厌乘车的颠簸,他希望在满足他的要求的情况下,旅行的距离尽量短,这样他就有足够的精力来欣赏风景或者是泡MM了

HDU 5434 Peace small elephant 状压dp+矩阵快速幂

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: 108 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 小明很喜欢国际象棋,尤其喜欢国际象棋里面的大象(只要无阻挡能够斜着走任意格),但是他觉得国际象棋里的大象太凶残了,于是他

【弱校胡策】2016.4.14 (bzoj2164)最短路+状压DP+矩阵乘法+高斯消元+树链剖分+线段树+背包DP

cyyz&qhyz&lwyz&gryz弱校胡策 命题人:cyyz ws_fqk T3暴力写挫了 50+10+0滚粗辣! 奇妙的约会(appointment.cpp/c/pas) [问题描述] DQS和sxb在网上结识后成为了非常好的朋友,并且都有着惊人 的OI水平.在NOI2333的比赛中,两人均拿到了金牌,并保送进入 HU/PKU.于是两人决定在这喜大普奔的时刻进行面基. NOI2333参赛选手众多,所以安排了n个考点,DQS在1号考点, 而sxb在n号考点.由于是举办全国性赛事