HDU 1401 双向状态搜索

第一次写双向状态搜索,输得这么惨,控制不了时间,有很多浪费的时间,不知道如何去控制,代码拍过三遍,最后一遍算是成功的,可是肯定超时,不知道如何优化它。。

只有等以后实力提高了再来搞定它。。

我得理解,每种状态有16种后继状态,可是当跳跃到下一步的时候,却写不出o(1)的判断,最后就成16*o(4) = 64;这样写不超时才叫怪事。。。搞了我三天了。。

贴上神牛的代码:

#pragma warning (disable:4786)
#include<stdio.h>
#include<queue>
#include<map>
using namespace std;
typedef struct p{
    int x,y;
}Point;
//共有四颗棋子,棋盘大小为64,采用位棋盘表示
typedef struct Map{
    unsigned __int64 value;
    Point p[4];
    int steps,which;
	void getvalue()
	{//棋盘对应键值
		value=0;
		for(short i=0;i<4;i++)
			value+=(unsigned __int64)1<<((p[i].x-1)*8+(p[i].y-1));
	}
}Map;
struct Cmp{
	bool operator () (const Map &a,const Map &b) const
	{
		return a.value<b.value;
	}
};
map<Map,int,Cmp>m;
queue<Map>q;
Map start,end;
int dir[][2]={{0,1},{0,-1},{1,0},{-1,0}};

bool Next(Map cur,Map &next,int ith,int d)
{//获取第ith个棋子d方向上的下一个棋面状态
    int i,j;
	
    next.p[ith].x=cur.p[ith].x+dir[d][0];
    next.p[ith].y=cur.p[ith].y+dir[d][1];
    
    if(next.p[ith].x<1||next.p[ith].x>8||next.p[ith].y<1||next.p[ith].y>8)
        return false;
    for(i=1;i<4;i++){
        if(next.p[ith].x==cur.p[(ith+i)%4].x&&next.p[ith].y==cur.p[(ith+i)%4].y){
            next.p[ith].x+=dir[d][0];
            next.p[ith].y+=dir[d][1];
            if(next.p[ith].x<1||next.p[ith].x>8||next.p[ith].y<1||next.p[ith].y>8)
                return false;
            for(j=1;j<4;j++){
                if(next.p[ith].x==cur.p[(ith+j)%4].x
                    &&next.p[ith].y==cur.p[(ith+j)%4].y)
                    return false;
            }
            return true;
        }
    }
    return true;
}
bool bfs()
{//双向搜索
    Map cur,next;
    int i,d,k,v;
    m.clear();
	while(!q.empty()) q.pop();
	start.steps=end.steps=0;
	start.which=1;end.which=2;
	start.getvalue();end.getvalue();
	m[start]=1;m[end]=2;
	q.push(start);q.push(end);
	
    while(!q.empty()){
        cur=q.front(); q.pop();
		v=m[cur];
		if(cur.steps>4)	break;
		if(v!=0&&v!=cur.which)	return true;
        for(i=0;i<4;i++){//每一颗棋子
            for(d=0;d<4;d++){//每一个方向
                if(Next(cur,next,i,d)){
                    for(k=1;k<4;k++)
                        next.p[(i+k)%4]=cur.p[(i+k)%4];
                    next.steps=cur.steps+1;
					next.which=cur.which;
                    next.getvalue();
					if(next.steps>4) continue;
					v=m[next];
                    if(v==next.which) continue;
					if(v&&v!=next.which) return true;
                    m[next]=next.which;
                    q.push(next);
                }
            }
        }
    }
    return false;
}
int main()
{
    int i;
	while(1){
		for(i=0;i<4;i++){
			if(scanf("%d%d",&start.p[i].x,&start.p[i].y)==EOF)
				return 0;
		}
		for(i=0;i<4;i++)
			scanf("%d%d",&end.p[i].x,&end.p[i].y);
		printf(bfs()?"YES/n":"NO/n");
	}
    return 0;
}

也附上我自己超时的代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;

struct node {
    int x[4],y[4];
};
queue<node>que;
int temp[8][8][8][8][8][8][8][8];
int s[8][8][8][8][8][8][8][8];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

void init(){
    while(!que.empty()) que.pop();
    memset(temp,0,sizeof(temp));
    memset(s,0,sizeof(s));
}

int judge(node te){
    if(s[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]]>=6){
        if(temp[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]]>8){ 
            cout<<"NO"<<endl;
            return 1;
        }    
        else { cout<<"YES"<<endl; return 1; }
    }
    if(temp[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]]>4) {
        cout<<"NO"<<endl; return 1;
    }
    return 0;
} 

int fan(node te){
    for(int i=0;i<4;i++){ 枚举每个棋子
        for(int j=0;j<4;j++){ 枚举四个方向 
            node p=te;
            p.x[i] += dir[j][0];
            p.y[i] += dir[j][1];
            if(p.x[i]<0 || p.y[i]>=8) continue;
            int flag=0;
            for(int r=0;r<4;r++){判断是否有棋子和它重合????超时根源 
                if(p.x[i]==p.x[r] && p.y[i]==p.y[r] && i!=r){
                    p.x[i]+=dir[j][0];再向前移一个位置 
                    p.y[i]+=dir[j][1];
                    if(p.x[i]<0 || p.y[i]>=8){ flag=1; break; }
                    for(int k=0;k<4;k++) ///判断是否还有棋子和它重合  ????超时根源
                        if(p.x[i]==p.x[k] && p.y[i]==p.y[k] && i!=k) flag=1;
                    if(flag) break; 
                    if(s[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]]///状态重合了 
                       ==s[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]) {
                       flag=1; break;
                    }    
                    if(!s[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]){///状态没有重合 
                       s[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]= 标记传递 
                       s[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]];   
                       temp[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]=步数叠加 
                       temp[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]]+1;
                       int ss = judge(p);
                       if(ss) return 1; 
                       que.push(p);
                       flag=1; break;
                    }
                    if(s[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]]///状态不同 
                       !=s[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]) {
                       s[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]] *=
                       s[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]];
                       temp[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]=步数叠加 
                       temp[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]]+1;
                       int ss = judge(p); 
                       if(ss) return 1;
                       flag=1; break;
                    } 
                }
            }
            if(flag) continue; 
            if(s[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]]///状态重合了 
                ==s[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]) {
                continue;
            }    
            if(!s[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]){///状态没有重合 
                s[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]= 标记传递 
                    s[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]];   
                    temp[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]=步数叠加 
                    temp[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]]+1;
                    int ss = judge(p);
                    if(ss) return 1; 
                    que.push(p);
                    continue;
            }
            if(s[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]]///状态不同 
                !=s[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]) {
                    s[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]] *=
                    s[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]];
                    temp[p.x[0]][p.y[0]][p.x[1]][p.y[1]][p.x[2]][p.y[2]][p.x[3]][p.y[3]]=步数叠加 
                    temp[te.x[0]][te.y[0]][te.x[1]][te.y[1]][te.x[2]][te.y[2]][te.x[3]][te.y[3]]+1;
                    int ss = judge(p); 
                    if(ss) return 1;
                    continue;
            } 
        }
    }
    return 0;
}

void BFS(){
    while(!que.empty()){
        node te=que.front();
        que.pop();
        if(judge(te)) break;
        int flag = fan(te);
        if(flag) break;
    }
}

int main(){
    int x[4],y[4],a[4],b[4];
    while(cin>>x[0]>>y[0]>>x[1]>>y[1]>>x[2]>>y[2]>>x[3]>>y[3]){
        for(int i=0;i<4;i++)
            cin>>a[i]>>b[i];
        for(int i=0;i<4;i++)
            x[i]--,y[i]--,a[i]--,b[i]--;
        init();
        temp[x[0]][y[0]][x[1]][y[1]][x[2]][y[2]][x[3]][y[3]]=1;
        temp[a[0]][b[0]][a[1]][b[1]][a[2]][b[2]][a[3]][b[3]]=1;
        s[x[0]][y[0]][x[1]][y[1]][x[2]][y[2]][x[3]][y[3]]=2;/第一个元素 
        if(!s[a[0]][b[0]][a[1]][b[1]][a[2]][b[2]][a[3]][b[3]])处理标记 
            s[a[0]][b[0]][a[1]][b[1]][a[2]][b[2]][a[3]][b[3]]=3;
        else s[a[0]][b[0]][a[1]][b[1]][a[2]][b[2]][a[3]][b[3]]*=3;
        node te;
        for(int i=0;i<4;i++){
            te.x[i]=x[i];
            te.y[i]=y[i];
        }
        que.push(te);
        for(int i=0;i<4;i++){
            te.x[i]=a[i];
            te.y[i]=b[i];
        }
        que.push(te);
        BFS();
    }
}
/*

4 4 4 5 5 4 6 5
4 4 4 5 5 4 6 5

4 4 4 5 5 4 6 5
2 4 3 3 3 6 4 6

*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值