您的位置:首页 > 大数据 > 人工智能

ZOJ 1430 / POJ 2679 The Erythea Campaign (bfs+dijkstra)

2010-08-28 00:07 549 查看
繁,但是不难。

首先,建图,题中给出的是m*n的矩阵,里面包含了所有stronghold的分布,但是你需要把他转换成一个图。但是路径不能穿过堡垒,多以说两个堡垒之间的两个点不能相互到达。还有就是每个点应该保存它可以到达的点的信息,当使用dijkstra求最短路径的时候,这些点可以当邻接表使用,很方便的。

接下来是每个的危险值,求法是m+n-d,不会出现负值。d的意思是它到达离他最近的堡垒的距离。对于每个堡垒上的点做bfs求出所有点到他的最短距离,如果求出的距离比之前更新的距离小的话,就存那个小的。

#include<iostream>
#include<cstring>
#include<queue>
const int INF = 99999999;
const int MAXLIST = 7000;
const int MAXMAP = 82;
using namespace std;
struct node
{
int value;        //危险值
bool isedge;    //是否是边界点
int order;      //点的序号
int reach[4];   //可以到达的点的序号
} map[MAXMAP][MAXMAP],list[MAXLIST];//list是类似于临接表的东西
int m,n;//n行,m列
char c;
int cases;
int startx,starty,endx,endy;  //开始和结束的坐标
int start,end;                //开始和结束的点在list里面的位置
int stronghold[MAXMAP][MAXMAP]; // 堡垒的分布
int flag[MAXLIST],dist[MAXLIST]; //dijkstra时候用的
void bfs(int n)                 //求出到所有点到n的距离
{
queue<int> q;
int inq[MAXLIST],t,dist;
for(int i= 0;i <MAXLIST;i++) inq[i] = 0;

inq
= 1;q.push(n);list
.value=0;
while( !q.empty() )
{
n = q.front();q.pop();
dist = list
.value+1;
for(int j=0; j < 4; j++)
{
t = list
.reach[j];
if( t==0 ) continue;
if( list[t].value > dist )
{    list[t].value = dist;
q.push(t);inq[t] = 1;}
}
}
}
void dijkstra(int a)
{
int now,min,v = (n+1)*(m+1);
for(int i=1;i <= v;i++)
{dist[i]=INF;flag[i]=0;}

dist[now=a] = list[a].value;flag[a] = 1;
for(int i = 1; i < v; i++)
{
for(int j = 0; j < 4; j++)
{
int to = list[now].reach[j];
if(to == 0) continue;
if( dist[to] > dist[now] + list[to].value )
dist[to] = dist[now] + list[to].value;
}
min = INF;
for(int j = 1; j <= v; j++)
if( !flag[j] && dist[j] < min )
min = dist[now=j];
flag[now] = 1;
}
}
int main(void)
{
cin >> cases;
while( cases-- )
{
cin >> n >> m;
cin >> startx >> starty >> endx >> endy;
starty++;endy++;
start = (m+1)*startx + starty;
end = (m+1)*endx + endy;
memset(stronghold,0,sizeof(stronghold));
for( int i = 0; i < n; i++ )                      //输入stronghold
{
getchar();
for( int j = 0; j < m; j++ )
stronghold[i][j] = (c=getchar()) - '0';
}
for( int i = 0,order = 1; i <= n; i++ )            //将图中的order和isedge初始化
for( int j = 0; j <= m; j++ )
{
map[i][j].order = order++;
map[i][j].isedge = false;
}

for( int i = 0; i < n; i++ )                        //判断某个点是不是堡垒的边界点
for( int j = 0; j < m; j++ )
if( stronghold[i][j] == 1 )
map[i][j].isedge = map[i+1][j].isedge =
map[i][j+1].isedge = map[i+1][j+1].isedge = 1;

for( int i = 0; i <= n; i++ )                        //点map【i】【j】可以到达的点在list中的位置
for( int j = 0; j <= m; j++ )                    //不可以到的为零
{
map[i][j].reach[0] = i>0?map[i-1][j].order:0;
map[i][j].reach[1] = j>0?map[i][j-1].order:0;
map[i][j].reach[2] = i<n?map[i+1][j].order:0;
map[i][j].reach[3] = j<m?map[i][j+1].order:0;
}

for( int i = 0; i < n; i++ )                            //两个堡垒相邻的话他们中间那个路不能走
for( int j = 0; j < m; j++ )
{
if( stronghold[i][j] == 1 && stronghold[i][j+1] == 1 )
map[i][j+1].reach[2] = map[i+1][j+1].reach[0] = 0;
if( stronghold[i][j] == 1 && stronghold[i+1][j] == 1 )
map[i+1][j].reach[3] = map[i+1][j+1].reach[1] = 0;
}
for( int i = 0,order = 1; i <= n; i++ )           //把map中的东西转移到list中
for( int j = 0; j <= m; j++ )
{
map[i][j].value = INF;
list[order++] = map[i][j];
}

for( int i = 0; i <= n; i++ )                  // 每个点的到所有堡垒边界点的最短距离
for( int j= 0; j <= m; j++ )
if( map[i][j].isedge )
bfs(map[i][j].order);
for(int i = 1;i <= (n+1)*(m+1); i++ )
list[i].value = m+n-list[i].value;           //危险值
dijkstra(start);
if (dist[end] == INF )
cout << "no solution/n";
else
cout << dist[end] <<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: