ACM 图论 搜索 SPFA UVALive 5966 Blade and Sword

ACM 图论 UVALive 5966

Blade and Sword


暴力 SPFA 写了8个小时才AC呀o(╯□╰)o

本题正解”双向“搜索,分两次从起点终点开始

其中后面那个代码是暴力,接近超时


E - Blade and Sword
Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu

Description

Download as PDF

You may have played the game 'Blade and Sword', it's an action game. However, in this problem we 
are actually solving one stage of the game.
For simplicity, assume that the game stage can be modeled as a 2D grid which has m rows and n 
columns. The cells are categorized as follows:
1) '.' represents an empty space. The player can move through it.
2) '#' represents wall, and the player cannot move through it. You can assume that the boundaries 
of the grid will be walls.
3) '*' means a teleporting cell, once the player moves into this cell, he must choose any other 
teleporting cell where he will be taken to. But if he cannot find a desired teleporting cell, he 
will die. However, after moving to the desired teleporting cell, he can either move to an 
adjacent cell, or he can teleport again using the same procedure.
4) 'P' means the position of the player and there will be exactly one cell containing 'P'.
5) 'D' means the destination cell and there will be exactly one cell containing 'D'.
Now you are given a stage and the player starts moving. It takes one unit of time for the player to 
move to any adjacent cell from his current position. Two cells are adjacent if they share a side. One 
unit of time is needed for the teleporting service; that means taking the player from one teleporting cell 
to any other teleporting cell. Your task is to find the minimum possible time unit required for the 
player to reach the destination cell.
Input
Input starts with an integer T (≤ 100), denoting the number of test cases.
Each case starts with a line containing two integers: m and n (3 ≤ m, n ≤ 200). Each of the next m 
lines contains n characters denoting the stage. The given stage follows the restrictions stated above.
Output
For each case, print the case number and the minimum required time. If it's impossible for the player 
to reach the destination cell, print 'impossible'. See the samples for details.

Sample Input
2
4 10
##########
#.P..#*..#
#*......D#
##########
3 9
#########
#P.#..D.#
#########

 Output for Sample Input

Case 1: 6
Case 2: impossible



Memory: 0 KB Time: 102 MS
Language: C++ 4.5.3 Result: Accepted

/*
 * Author:  vawait
 * Created Time:  2014/8/3 12:46:19
 * File Name: test.cpp
 */
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
using namespace std;
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define red(i, a, b) for (int i = (a); i >= (b); --i)
#define clr( x , y ) memset(x,y,sizeof(x))
#define mp make_pair
#define pb push_back
#define x first
#define y second
#define sqr(x) ((x) * (x))
#define num( i , j ) ( ( i - 1 ) * m + j )
typedef long long lint;
int n , m , d[40010] , S , T , s , qs[80010];
int dx[] = { 0 , 0 , 1 , -1 };
int dy[] = { 1 , -1 , 0 , 0 };
vector < int > a[40010];
pair < int , int > q1[80010] , q2[80010];
char c[300][300];

void init()
{
    scanf("%d%d",&n,&m);
    red(i,n*m,0) a[i].clear();
    s = 0;
    rep(i,1,n) scanf("%s",c[i]+1);
    rep(i,1,n)
        rep(j,1,m) if ( c[i][j] != '#' ) {
            if ( c[i][j] != '*' ) rep(k,0,3) {
                int x = i + dx[k] , y = j + dy[k];
                if ( x >= 1 && x <= n && y >= 1 && y <= m )
                    a[num( i , j )].pb( num( x , y ) );
            }
            if ( c[i][j] == '*' ) qs[++s] = num( i , j );
            if ( c[i][j] == 'P' ) S = num( i , j );
            if ( c[i][j] == 'D' ) T = num( i , j );
        }
}

void work()
{
    queue < int > q;
    int x , y;
    q.push( S ); 
    clr( d , 1 ); 
    d[S] = 0;
    while ( !q.empty() ) {
        x = q.front() ; q.pop();
        red(i,a[x].size()-1,0) if ( d[y=a[x][i]] > 1000000 ) {
            d[y] = d[x] + 1;
            q.push( y );
        }
    }
    
    rep(i,1,s) q1[i].x = d[qs[i]] , q1[i].y = i;
    
    int ans = d[T];
    q.push( T ); 
    clr( d , 1 ); d[T] = 0;
    while ( !q.empty() ) {
        x = q.front() ; q.pop();
        red(i,a[x].size()-1,0) if ( d[y=a[x][i]] > 1000000 ) {
            d[y] = d[x] + 1;
            q.push( y );
        }
    }
    rep(i,1,s) q2[i].x = d[qs[i]] , q2[i].y = i;
    if ( s ) sort( q1 + 1 , q1 + s + 1 );
    if ( s ) sort( q2 + 1 , q2 + s + 1 );
    
    red(i,min(2,s),1)
        red(j,min(2,s),1) {
            if ( q1[i].y != q2[j].y ) ans = min( ans , q1[i].x + 1 + q2[j].x );
            else if ( s > 1 ) ans = min( ans , q1[i].x + 2 + q2[j].x );
        }
    if ( ans < 1000000 ) printf("%d\n",ans); else puts("impossible");
}

int main()
{
    int t;
    cin >> t;
    rep(i,1,t) {
        printf("Case %d: ",i);
        init();
        work();
    }
    return 0;
}


Memory: 0 KB Time: 2713 MS
Language: C++ 4.5.3 Result: Accepted

/*
 * Author: NICK WONG
 * Created Time:  8/3/2014 14:32:53
 * File Name: e.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=210;
const long long maxint=-1u>>1;
const long long maxlong=maxint*maxint;
typedef long long lint;
typedef int point[2];
struct node
{
    int x,y,len,type,tele;
    //node(int x=0,int y=0,int len=0,int type=0,bool tele=0):
     //   x(x),y(y),len(len),type(type),tele(tele) {};
};
point tele1,tele2,st,en,star[maxn*maxn],tmp[5];
char a[maxn][maxn];
int n,m,t,dis[maxn][maxn],arr[maxn][maxn],lim,tmplen[5];
queue<node> q;
const int step[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

void init()
{
    star[0][0]=0;
    char c;
    scanf("%c",&c);
    for (int i=1; i<=n; i++)
    {
        for (int j=1; j<=m; j++)
        {
            scanf("%c",&a[i][j]);
            if (a[i][j]=='P') {st[0]=i; st[1]=j;} else
                if (a[i][j]=='D') {en[0]=i; en[1]=j;} //else
                    //if (a[i][j]=='*') {star[++star[0][0]][0]=i; star[star[0][0]][1]=j; }
        }
        scanf("%c",&c);
    }
    for (int i=0; i<=n+1; i++) a[i][0]=a[i][m+1]='#';
    for (int j=0; j<=m+1; j++) a[0][j]=a[n+1][j]='#';
}

void spfa()
{
    int mytype;
    memset(dis,-1,sizeof(dis));
    memset(arr,-1,sizeof(arr));
    node x={st[0],st[1],0,0,0};
    q.push(x); dis[st[0]][st[1]]=0;
    while (q.size())
    {
        x=q.front(); q.pop();
        if (x.type==0)
        {
            for (int i=0; i<=3; i++)
            {
                int u=x.x+step[i][0]; int v=x.y+step[i][1];
                if (a[u][v]!='#' && (x.len+1<dis[u][v] || dis[u][v]<0))
                {
                    dis[u][v]=x.len+1;
                    if (a[u][v]=='*') mytype=1; else mytype=0;
                    if (a[u][v]=='*' && (x.tele>=lim)) continue;
                    if (u==en[0] && v==en[1]) return;
                    node y={u,v,dis[u][v],mytype,x.tele};
                    q.push(y);
                }
            }
        } else
        if (x.type==1 && (x.tele<lim))
        {
            for (int i=1; i<=star[0][0]; i++)
            {
                int u=star[i][0]; int v=star[i][1];
                if ((u==x.x && v==x.y)) continue;
                if (x.len+1<arr[u][v] || arr[u][v]<0)
                {
                    arr[u][v]=x.len+1;
                    node y={u,v,arr[u][v],2,x.tele+1};
                    q.push(y);
                }
            }
        } else
        if (x.type==2)
        {
            for (int i=0; i<=3; i++)
            {
                int u=x.x+step[i][0]; int v=x.y+step[i][1];
                if (a[u][v]!='#' && a[u][v]!='*' && (x.len+1<dis[u][v] || dis[u][v]<0))
                {
                    dis[u][v]=x.len+1;
                    if (a[u][v]=='*') mytype=1; else mytype=0;
                    node y={u,v,dis[u][v],mytype,x.tele};
                    if (u==en[0] && v==en[1]) return;
                    q.push(y);
                }
            }
            if (x.tele<lim)
            for (int i=1; i<=star[0][0]; i++)
            {
                int u=star[i][0]; int v=star[i][1];
                if ((u==x.x && v==x.y)) continue;
                if (x.len+1<arr[u][v] || arr[u][v]<0)
                {
                    arr[u][v]=x.len+1;
					node y={u,v,arr[u][v],2,x.tele+1};
                    q.push(y);
                }
            }
        }
    }
}

void check(int x, int y,int len)
{
    dis[x][y]=1;
    for (int i=0; i<=3; i++)
    {
        int u=x+step[i][0]; int v=y+step[i][1];
        if (a[u][v]=='*') 
        	if (len+1<tmplen[1]) 
        	{
        		tmplen[2]=tmplen[1];
	        	tmp[2][0]=tmp[1][0]; tmp[2][1]=tmp[1][1];
	        	tmplen[1]=len+1;
	        	tmp[1][0]=u; tmp[1][1]=v;
	        } else
	        if (len+1<tmplen[2]) 
        	{
	        	tmplen[2]=len+1;
	        	tmp[2][0]=u; tmp[2][1]=v;
	        }
        if (dis[u][v]==-1 && a[u][v]!='#' && a[u][v]!='*')
        {
            dis[u][v]=1;
            check(u,v,len+1);
        }
    }
}

void work()
{
	lim=2;
    memset(dis,-1,sizeof(dis));
    tmplen[1]=tmplen[2]=maxint;
    check(st[0],st[1],0);
    for (int i=1; i<=2; i++)
    	if (tmplen[i]!=maxint)
		{
			star[++star[0][0]][0]=tmp[i][0]; 
			star[star[0][0]][1]=tmp[i][1]; 
		}
		
	memset(dis,-1,sizeof(dis));
    tmplen[1]=tmplen[2]=maxint;
    check(en[0],en[1],0);
    for (int i=1; i<=2; i++)
    	if (tmplen[i]!=maxint) 
		{
			star[++star[0][0]][0]=tmp[i][0]; 
			star[star[0][0]][1]=tmp[i][1]; 
		}
	bool wjj=false;
	for (int i=1; i<=n; i++)
		for (int j=1; j<=m; j++)
		{
			if (wjj) break;
			bool flag=true;
			if (a[i][j]!='*') continue;	
			for (int k=1; k<=star[0][0]; k++)
 			{
  				int u=star[k][0]; int v=star[k][1];
  				if (u==i && v==j) flag=false;
 			}
 			if (flag)
 			{
			 	star[++star[0][0]][0]=i; 
				star[star[0][0]][1]=j; 
		 	}
		}		
  		
    //if (dis[en[0]][en[1]]==-1) lim=2; else lim=1; 
    //near_tele(st,tele1);
    //near_tele(en,tele2);
    while(q.size()) q.pop();
    spfa();
    cout<<"Case "<<t<<": ";
    if (dis[en[0]][en[1]]==-1) cout<<"impossible"<<endl; else cout<<dis[en[0]][en[1]]<<endl;
}


int main()
{
    int test;
    cin>>test;
    for (t=1; t<=test; t++)
    {
        cin>>n>>m;
        init();
        work();
    }
    return 0;
}

/*void near_tele(point en,point tele)
{
    tele[0]=tele[1]=0;
    bool flag=false;
    memset(dis,-1,sizeof(dis));
    memset(arr,-1,sizeof(arr));
    node x(en[0],en[1],0,0,false);
    q.push(x); dis[en[0]][en[1]]=0;
    while(q.size())
    {
        x=q.front(); q.pop();
        if (flag) break;
        for (int i=0; i<=3; i++)
        {
            int u=x.x+step[i][0]; int v=x.y+step[i][1];
            if (a[u][v]!='#' && (x.len+1<dis[u][v] || dis[u][v]<0))
            {
                dis[u][v]=x.len+1;
                if ((!flag) && a[u][v]=='*')
                {
                    tele[0]=u; tele[1]=v;
                    flag=true;
                }
                q.push(node(u,v,dis[u][v]));
            }
        }
    }
    while(q.size())
    {
       q.pop();
    }
}*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值