http://acm.hdu.edu.cn/showproblem.php?pid=4568

Hunter

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1254    Accepted Submission(s): 367
Problem Description
  One day, a hunter named James went to a mysterious area to find the treasures. James wanted to research the area and brought all treasures that he could.

  The area can be represented as a N*M rectangle. Any points of the rectangle is a number means the cost of research it,-1 means James can't cross it, James can start at any place out of the rectangle, and explore point next by next. He will move in the rectangle
and bring out all treasures he can take. Of course, he will end at any border to go out of rectangle(James will research every point at anytime he cross because he can't remember whether the point are researched or not).

  Now give you a map of the area, you must calculate the least cost that James bring out all treasures he can take(one point up to only one treasure).Also, if nothing James can get, please output 0.

 
Input
  The input consists of T test cases. The number of test cases T is given in the first line of the input. Each test case begins with a line containing 2 integers N M , (1<=N,M<=200), that represents the rectangle. Each of the following
N lines contains M numbers(0~9),represent the cost of each point. Next is K(1<=K<=13),and next K lines, each line contains 2 integers x y means the position of the treasures, x means row and start from 0, y means column start from 0 too.
 
Output
  For each test case, you should output only a number means the minimum cost.
 
Sample Input
2
3 3
3 2 3
5 4 3
1 4 2
1
1 1
3 3
3 2 3
5 4 3
1 4 2
2
1 1
2 2
 
Sample Output
8
11
 

题意:给一个n行m列的迷宫,每个格子都有数字代表花费,-1代表这个格子无法通过,然后给出k个放有宝石的格子的坐标,每个格子最多有一个宝石,问从边缘进入迷宫拿出所有的所有的宝石再从边缘出去的最小花费,每个格子可以走多次;

分析:首先这道题题意特蛋疼,首先这种情况:

5 5

1 1 1 1 1

1 -1 -1 -1 -1

1 -1 1 1 1

1 -1 1 1 1

1 -1 1 1 1

2

0 0

4 4

两个宝石完全被隔开,如果只进出一次是没办法全部拿出来的,可以进出多次的话可以,但是题目中也没说是不是只能进入一次,加入只能进入一次,但是拿不完输出什么,题目中也没有说,还有一种情况:

5 5

1 1 1 1 1

1 -1 -1 -1 1

1 -1 1 -1 1

1 -1 -1 -1 1

1 1 1 1 1

1

2 2

无论怎么拿都拿不出来,此时应该输出0吗,但是你只有进去了才知道拿不出完,只要进去了就有花费应该怎么输出呢?费解。。。。。。

但是以上测试数据时没有的,那这就简单了;

首先BFS+优先队列,求出宝石之间的最短距离,顺便求出每个宝石到边缘的距离,存在dist中,注意dist包含两个端点的费用,然后把两端的费用去掉放在dis中,接下来就是典型的TSP问题了,用状压DP求拿出所有宝石的状态即可;

最后的结果+所有宝石的费用;

#include"stdio.h"
#include"string.h"
#include"iostream"
#include"map"
#include"string"
#include"queue"
#include"stdlib.h"
#include"algorithm"
#include"math.h"
#define M (1<<15)+2
#define eps 1e-10
#define inf 100000000
#define mod 100000000
#define INF 0x3f3f3f3f
using namespace std;
int dp[M][17],dist[222][222],use[222][222],vis[222][222];
int mp[222][222],px[20];
int dis[17][17];
int disx[5]={0,1,0,-1};
int disy[5]={1,0,-1,0};
int n,m;
struct node
{
int x,y,t;
friend bool operator<(node a,node b)
{
return a.t>b.t;
}
};
int min(int a,int b)
{
return a<b?a:b;
}
int bfs(int x,int y)
{
int mini=INF,i;
priority_queue<node>q;
memset(dist,INF,sizeof(dist));
memset(vis,0,sizeof(vis));
node now;
now.x=x;
now.y=y;
now.t=mp[x][y];
vis[now.x][now.y]=1;
q.push(now);
while(!q.empty())
{
node cur=q.top();
q.pop();
for(i=0;i<4;i++)
{
now.x=cur.x+disx[i];
now.y=cur.y+disy[i];
if(now.x<0||now.y<0||now.x>=n||now.y>=m)
{
if(mini>cur.t)
mini=cur.t;
continue;
}
if(mp[now.x][now.y]==-1)continue;
now.t=cur.t+mp[now.x][now.y];
if(dist[now.x][now.y]>now.t)
{
dist[now.x][now.y]=now.t;
if(!vis[now.x][now.y])
{
vis[now.x][now.y]=1;
q.push(now);
}
}
if(now.x==0||now.y==0||now.x==n-1||now.y==m-1)
{
if(mini>now.t)
mini=now.t;
} }
}
return mini;
}
void DP(int cnt)
{
int i,j,k;
memset(dp,INF,sizeof(dp));
dp[1][0]=0;
dp[1<<(cnt-1)][cnt-1]=0;
int ff=0;
ff|=1;
ff|=1<<(cnt-1);
for(i=1;i<px[cnt];i++)
{
if((i&ff)==0)continue;
for(j=0;j<cnt;j++)
{
int tep=i&(1<<j);
if(tep==0)continue;
int cur=i^(1<<j);
for(k=0;k<cnt;k++)
{
if((cur&(1<<k))==0||k==j)continue;
if(dp[cur][k]>=INF||dis[k][j]>=INF)continue;
if(dp[i][j]>dp[cur][k]+dis[k][j])
dp[i][j]=dp[cur][k]+dis[k][j];
}
}
}
}
struct Node
{
int x,y,val;
}p[20];
int main()
{
int T,i,j,fuck,x,y;
px[0]=1;
for(i=1;i<=15;i++)
px[i]=px[i-1]*2;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
scanf("%d",&mp[i][j]);
scanf("%d",&fuck);
int cnt=1;
int ans=0;
for(i=0;i<fuck;i++)
{
scanf("%d%d",&x,&y);
ans+=mp[x][y];
p[cnt].x=x;
p[cnt].y=y;
p[cnt].val=mp[x][y];
cnt++;
}
memset(dis,INF,sizeof(dis));
for(i=1;i<cnt;i++)
{
int L=bfs(p[i].x,p[i].y);
if(L<INF)
dis[0][i]=dis[i][0]=dis[i][cnt]=dis[cnt][i]=L-mp[p[i].x][p[i].y];
for(j=1;j<cnt;j++)
{
if(i==j)dis[i][j]=INF;
else
{
if(dist[p[j].x][p[j].y]<INF)
dis[i][j]=dist[p[j].x][p[j].y]-mp[p[i].x][p[i].y]-mp[p[j].x][p[j].y];
}
}
}
cnt++;
DP(cnt);
if(dp[px[cnt]-1][0]<INF)
printf("%d\n",ans+dp[px[cnt]-1][0]);
else
printf("0\n");
}
}

BFS+优先队列+状态压缩DP+TSP的更多相关文章

  1. HDU 3681 Prison Break(BFS+二分+状态压缩DP)

    Problem Description Rompire is a robot kingdom and a lot of robots live there peacefully. But one da ...

  2. HDU 4856 (状态压缩DP+TSP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4856 题目大意:有一个迷宫.迷宫里有些隧道,每个隧道有起点和终点,在隧道里不耗时.出隧道就耗时,你的 ...

  3. HDU 5067 (状态压缩DP+TSP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5067 题目大意:蓝翔挖掘机挖石子.把地图上所有石子都运回起点,问最少耗时. 解题思路: 首先得YY出 ...

  4. HOJ 2226&POJ2688 Cleaning Robot(BFS+TSP(状态压缩DP))

    Cleaning Robot Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4264 Accepted: 1713 Descri ...

  5. BFS+状态压缩DP+二分枚举+TSP

    http://acm.hdu.edu.cn/showproblem.php?pid=3681 Prison Break Time Limit: 5000/2000 MS (Java/Others)   ...

  6. HDU 3681 Prison Break(状态压缩dp + BFS)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 前些天花时间看到的题目,但写出不来,弱弱的放弃了.没想到现在学弟居然写出这种代码来,大吃一惊附加 ...

  7. HDU 3247 Resource Archiver (AC自己主动机 + BFS + 状态压缩DP)

    题目链接:Resource Archiver 解析:n个正常的串.m个病毒串,问包括全部正常串(可重叠)且不包括不论什么病毒串的字符串的最小长度为多少. AC自己主动机 + bfs + 状态压缩DP ...

  8. TSP 旅行商问题(状态压缩dp)

    题意:有n个城市,有p条单向路径,连通n个城市,旅行商从0城市开始旅行,那么旅行完所有城市再次回到城市0至少需要旅行多长的路程. 思路:n较小的情况下可以使用状态压缩dp,设集合S代表还未经过的城市的 ...

  9. 最短路+状态压缩dp(旅行商问题)hdu-4568-Hunter

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4568 题目大意: 给一个矩阵 n*m (n m<=200),方格里如果是0~9表示通过它时要花 ...

随机推荐

  1. 【这特么是个坑。。。】iOS 10.3下解决Charles抓包ssl证书信任问题

    针对近期iOS 10.3以上的系统charles抓https信任问题 前言 最近iPhone系统更新到ios 10.3后,在公司里用Charles抓包竟然出现了一些问题,https的请求都会失败,提示 ...

  2. [Spring] Java spring quartz 定时任务

    首先,需要导入quartz 的jar包 ① applicationContext.xml <!-- 轮询任务 --> <import resource="classpath ...

  3. Openfire配置过程,以及与php交互注意事项。

    Ben Werdmuller 是一位 Web 策划师和开发人员,他专注于开放源码平台.他是开源社交网络框架 Elgg 的共同创始人和技术带头人.Ben 的博客 http://benwerd.com/. ...

  4. 关于Unity的入门游戏飞机大战的开发(上)

    每个组件都是一个类的实例,要获得某个组件,要先创建一个同类型的组件类实例,然后把实例传引用过去,就可以对想要的组件实例进行操作. 做游戏一般创建一个逻辑节点,里面只管逻辑,再创建一个动画节点,里面有好 ...

  5. 【转】WCF入门教程五[WCF的通信模式]

    一.概述 WCF在通信过程中有三种模式:请求与答复.单向.双工通信.以下我们一一介绍. 二.请求与答复模式 描述: 客户端发送请求,然后一直等待服务端的响应(异步调用除外),期间处于假死状态,直到服务 ...

  6. C++ 数据抽象

    C++ 数据抽象数据抽象是指,只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节. 数据抽象是一种依赖于接口和实现分离的编程(设计)技术. 让我们举一个现实生活中的真实例子, ...

  7. Adobe AIR(跨平台应用)

    Adobe AIR(跨平台应用)现在正式应用于android平台了,Adobe Air是一款独立的客户端应用软件,这些软件可以作为单独的程序安装使用,它可以使开发人员使用HTML.JavaScript ...

  8. bedtools 的安装与使用

    1) 安装 bedtools 提供了3种安装方式 从google code 下载源代码进行安装 利用系统中的包管理工具进行安装, 比如cnetos 下的yum, ubuntu下的apt-get, ma ...

  9. 深入浅出Redis-redis哨兵集群[转]

    1.Sentinel 哨兵 Sentinel(哨兵)是Redis 的高可用性解决方案:由一个或多个Sentinel 实例 组成的Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所 ...

  10. solr 5.2.1 tomcat 7 配置过程笔记

    因为这个是新版,网上很少这个配置文档,看网上其他的教程弄了很多次,都没有成功,幸亏有这个链接的文档, 才迅速的配置成功,其实是比以前简洁了.因为我的在 linux 上面安装,不方便截图,直接复制修改了 ...