2016 UESTC Traing Search Algorithm &String Problem N 简单的双向搜索


题目链接:点击打开链接

N - 简单的双向搜索

Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 131072/131072KB (Java/Others)

给定三个大小为 N 的整型数组 A1,A2,A3 ,和三个整数 B1,B2,B3 。接下来依次做 N 次操作:对于第 i 次操作 (i=1,2,..,N) ,选择一个数 j ( j=1,2,3 ),令 Bj 加上 Aj[i] 。问是否存在一种操作序列,使得最后 B1=B2=B3=0

Input

第一行四个数 N(1<=N<=25),B1,B2,B3 。接下来N行,每行三个整数,表示 A1[i],A2[i] A3[i] 。保证 |A1[i]|,|A2[i]|,|A3[i]|,|B1|,|B2|,|B3|<=109

Output

如果存在符合要求的方案,输出 "YES" ;否则输出 "NO"


这是双向搜索的入门题,也是经典的选数问题,双向bfs相对于单向bfs无论是在时间还是空间复杂度上都优于单向bfs,bfs实际上任然是一种盲目搜索算法,它考虑完一个层次后,才会考虑下一个层次,所以状态数成指数级增长,对空间消耗非常大,如果已知目标状态,我们考虑使用双向bfs,空间消耗在指数上大约能减少一半;对于这道题,由于这不是一道求最短路的问题,而是一道判断题,所以我们不需要记忆化搜索,我们先正向走n/2步,此时,用map保存,反向走n-n/2步,查此时的状态是否在map中出现过。

#include<bits/stdc++.h>
using namespace std;
int a[3][30];
struct node1{
	int b[3];
	int step;
};
vector<int>v;
map<vector<int>,int>m3;
queue<node1>q1;
queue<node1>q2;
int main()
{
	int b[3],n,i,j,k;
	scanf("%d %d %d %d",&n,&b[0],&b[1],&b[2]);
	for(i=0;i<n;i++)
		for(j=0;j<3;j++)
	scanf("%d",&a[j][i]);
	struct node1 sta,des;
	for(i=0;i<3;i++)
	sta.b[i]=b[i];
	sta.step=0;
	for(j=0;j<3;j++)
	des.b[j]=0;
	des.step=0;
	q1.push(sta);
	q2.push(des);
	struct node1 x,y;
	v.resize(3);
while(1)
{
	if(!q1.empty())//正向走n/2步 
	{
		x=q1.front();
		if(x.step==n/2)
		break;
		q1.pop();
		for(i=0;i<3&&x.step<n;i++)
		{
			y=x;
			y.b[i]+=a[i][y.step];
			y.step++;
			if(y.step==n/2)//存入容器中 
			{
				v[0]=y.b[0];
				v[1]=y.b[1];
				v[2]=y.b[2];
				m3[v]=1;
				continue;
			}
			q1.push(y);
		}
	}
	else
	break;
}
while(1)
{
	if(!q2.empty())//反向走n-n/2步 
	{
		x=q2.front();
		if(x.step>n-n/2)
		{
			printf("NO");
			return 0;
		}
		q2.pop();
		for(i=0;i<3&&x.step<n;i++)
		{
			y=x;
			y.b[i]-=a[i][n-y.step-1];
			y.step++;
			if(y.step==n-n/2)//比较 
			{
				v[0]=y.b[0];
				v[1]=y.b[1];
				v[2]=y.b[2];
				if(m3.count(v))
				{
					printf("YES");
					return 0;
				}
				continue;
			}
			q2.push(y);
		}
	}
	else
	{
		printf("NO");
		return 0;
	}
	
}
return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值