kuangbin带你飞 专题一

1 篇文章 0 订阅
0 篇文章 0 订阅

kuangbin在vjudge上面挂了一些专题,感谢bin神带我飞~

Problem APOJ1321

中文题目 DFS 注意某一行可以不放棋子,因此需要在DFS函数后面加一个dfs(row+1,num)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
int visit[10],tot,n,k;
int ch[10][10];
void dfs(int row,int num)
{
	int j;
	if(num==k)
	{
		tot++;
		return;
	}
	if(row>n)
		return;
	for(j=1;j<=n;j++)
		if(ch[row][j]&&!visit[j])
		{
			visit[j]=1;
			dfs(row+1,num+1);
			visit[j]=0;
		}
	dfs(row+1,num);
	return;
}
int main()
{
	int i,j;
	char x;
	while(scanf("%d%d",&n,&k)!=EOF&&(n!=-1||k!=-1))
	{
		getchar();
		memset(ch,0,sizeof(ch));
		memset(visit,0,sizeof(visit));
		tot=0;
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
			{
				scanf("%c",&x);
				if(x=='#')
					ch[i][j]=1;
				if(j==n)
					getchar();
			}
		dfs(1,0);
		printf("%d\n",tot);
	}
	return 0;
} 

Problem B

POJ2251

三维的,共有6个方向,BFS,很水

#include <iostream>
#include <queue>
#include <cstring>
#include<cstdio> 
using namespace std;
int l,r,c;
char g[31][31][31];
int shift[6][3]={{-1,0,0},{1,0,0},{0,-1,0},{0,1,0},{0,0,-1},{0,0,1}};
short flag[31][31][31];
int s[3];
int e[3];
int min_path=0xffff;
struct Point
{
		int x;
		int y;
		int z;
		int step;
};
queue<Point> mq;
bool inrange(int x,int y,int z)
{
		if(x>=0 && x<l && y>=0 && y<r && z>=0 && z<c)
				return true;
		else
				return false;
}
void bfs(int x,int y,int z)
{
	Point p;
	p.x=x;
	p.y=y;
	p.z=z;
	p.step=0;
	flag[x][y][z]=1;
	mq.push(p);
	while(!mq.empty())
	{
			Point q = mq.front();
			mq.pop();
		
			if(q.x==e[0] && q.y==e[1] && q.z==e[2])	
			{
					min_path = q.step;
					return;
			}
			for(int i=0;i<6;i++)
			{
					Point m;
					m.x= q.x+shift[i][0];
					m.y= q.y+shift[i][1];
					m.z= q.z+shift[i][2];
					m.step =q.step+1;
				if(inrange(m.x,m.y,m.z) && g[m.x][m.y][m.z]!='#'  && flag[m.x][m.y][m.z]==0)
				{
						flag[m.x][m.y][m.z]=1;
						mq.push(m);
				}
			}
	}
}
int main()
{
	cin>>l;
	cin>>r;
	cin>>c;	
	int i,j,k;
	while(l || r || c)
	{
			min_path=0xffff;
			memset(g,0,sizeof(g));
			memset(flag,0,sizeof(flag));
			while(!mq.empty())
			{
					mq.pop();
			}
			for(i=0;i<l;i++)
			{
					for(j=0;j<r;j++)
					{
							getchar();
							for(k=0;k<c;k++)
							{
									g[i][j][k]=getchar();
									if(g[i][j][k]=='S')
									{
											s[0]=i;
											s[1]=j;
											s[2]=k;
									}
									if(g[i][j][k]=='E')
									{
											e[0]=i;
											e[1]=j;
											e[2]=k;
									}
							}
					}
					getchar();
			}
			bfs(s[0],s[1],s[2]);
			if(min_path<0xffff)
					cout<<"Escaped in "<<min_path<<" minute(s)."<<endl;
			else
					cout<<"Trapped!"<<endl;
			cin>>l;
			cin>>r;
			cin>>c;	
	}
	
}
Problem C

POJ3278

BFS水题 n经过多次+1or-1or*2后得到n

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
int n,k,ans;
int visit[200005];
struct pos
{
	int x;
	int t;
};
queue<pos>s;
void bfs(int x)
{
	pos b;
	b.x=x;
	b.t=0;
	visit[x]=1;
	s.push(b);
	while(!s.empty())
	{
		pos m=s.front();
		s.pop();
		if(m.x==k)
		{
			ans=m.t;
			return;
		}
		pos q;
		q.x=m.x-1;
		q.t=m.t+1;
		if(q.x>=0&&q.x<=100000&&visit[q.x]==0)
		{
			visit[q.x]=1;
			s.push(q);
		}
		q.x=m.x+1;
		q.t=m.t+1;
		if(q.x>=0&&q.x<=100000&&visit[q.x]==0)
		{
			visit[q.x]=1;
			s.push(q);
		}
		q.x=m.x*2;
		q.t=m.t+1;
		if(q.x>=0&&q.x<=100000&&visit[q.x]==0)
		{
			visit[q.x]=1;
			s.push(q);
		}
	}
}
int main()
{
	while(scanf("%d%d",&n,&k)!=EOF)
	{
		memset(visit,0,sizeof(visit));
		while(!s.empty())
			s.pop();
		bfs(n);
		printf("%d\n",ans);
	}
	return 0;
} 

Problem D

POJ3279

翻白块,开始想了好久,枚举第一行,后面的状态就可以确定了,因为上面一行没有翻过来的白块只有通过下一行才能翻过来

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define INF 0x7fffffff
using namespace std;
int n,m,mint;
int dir_x[4]={0,0,1,-1};
int dir_y[4]={1,-1,0,0};
int map[16][16],t[16][16],ans[16][16],op[16][16];
void operate(int x,int y)
{
	op[x][y]=1;
	t[x][y]^=1;
	for(int k=0;k<4;k++)
	{
		int nowx=x+dir_x[k];
		int nowy=y+dir_y[k];
		if(nowx<1||nowy<1||nowx>n||nowy>m)
			continue;
		t[nowx][nowy]^=1; 
	}
}
void solve(int x)
{
	int tot=0; 
	memset(op,0,sizeof(op));
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			t[i][j]=map[i][j];
	for(int i=1;i<=m;i++)
		if((1<<(i-1))&x)
		{
			tot++;
			if(tot>=mint)
				return;
			operate(1,m-i+1);
		}
	for(int i=2;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			if(t[i-1][j])
			{
				tot++;
				if(tot>=mint)
					return;
				operate(i,j);
			}
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(t[i][j])
				return;
	mint=tot;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			ans[i][j]=op[i][j];
}
int main()
{
	int i,j;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(i=1;i<=n;i++)
			for(j=1;j<=m;j++)
				scanf("%d",&map[i][j]);
		mint=INF-10;
		for(i=0;i<=((1<<m)-1);i++)
			solve(i);
		if(mint!=INF-10)
		{
			for(i=1;i<=n;i++)
			{
				for(j=1;j<m;j++)
					printf("%d ",ans[i][j]);
				printf("%d\n",ans[i][m]);
			}
		}
		else printf("IMPOSSIBLE\n");
	}
	return 0;
} 
Problem E

POJ1426

一开始想的很复杂。。。后来发现只是个简单的DFS

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
 bool found;
 void DFS(unsigned __int64 t ,int n,int k)
 {
     if(found)
         return ;//如果已经发现了答案就没搜的必要了
     if(t%n==0)
     {//发现答案,输出,标记变量该true
         printf("%I64u\n",t);
        found=true;
         return ;
     }
     if(k==19)//到第19层,回溯
         return ;
     DFS(t*10,n,k+1);    //搜索×10
     DFS(t*10+1,n,k+1);    //搜索×10+1
 }
 int main()
 {
     int n;
     while(cin>>n,n)
     {
         found=false;//标记变量,当为true代表搜到了题意第一的m
         DFS(1,n,0);    //从1开始搜n的倍数,第三个参数代表搜的层数,当到第19层时返回(因为第20层64位整数存不下)
    }
     return 0;
}

Problem F

POJ3126

素数打表DFS搞定

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
int f[10000],prime[10000],visit[10000];
int x,tag;
struct state
{
	int w[4];
	int t;
};
void isprime()
{
	memset(prime,0,sizeof(prime));
	memset(f,0,sizeof(f));
	for(int i=2;i<=9999;i++)
	{
		if(f[i]==0)
		{
			for(int j=i+i;j<=9999;j+=i)
				f[j]=1;
			prime[i]=1;
		}
	}
} 
void bfs()
{
	int i,j;
	queue<state>s;
	state p; 
	p.w[0]=x/1000;
	p.w[1]=(x-p.w[0]*1000)/100;
	p.w[3]=x%10;
	p.w[2]=(x-1000*p.w[0]-100*p.w[1]-p.w[3])/10;
	p.t=0;
	s.push(p);
	memset(visit,0,sizeof(visit));
	visit[x]=1;
	while(!s.empty())
	{
		state q,n;
		q=s.front();
		s.pop();
		int now=q.w[0]*1000+q.w[1]*100+q.w[2]*10+q.w[3];
		//	printf("%d\n",now);
		//	getchar();
		if(now==tag)
		{
			printf("%d\n",q.t);
			return;
		}
		for(i=0;i<=3;i++)
			for(j=0;j<=9;j++)
			{
				n=q;
				n.w[i]=j;
				n.t=q.t+1;
				int sum=n.w[0]*1000+n.w[1]*100+n.w[2]*10+n.w[3];
				if(!visit[sum]&&prime[sum]&&sum>1000)
				{
				//	printf("%d\n",sum);
					s.push(n);
					visit[sum]=1;
				}
			}
	}
	printf("Impossible\n");
}
int main()
{
	int t,i;
	isprime();
	while(scanf("%d",&t)!=EOF)
	{
		while(t--)
		{
			scanf("%d%d",&x,&tag);
			bfs();
		} 
	}
	return 0;
} 

Problem G

POJ3087

模拟,如果回到初态说明不能成功,看到了一个特别短的代码,拿来引用了,很简洁,一看便懂

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
	int i,n,t,j,m,k;
	char s1[201],s2[201],s[201],s0[201],stag[401];
	while(scanf("%d",&m)!=EOF)
	{
		for(k=1;k<=m;k++)
		{
			scanf("%d",&n);
			scanf("%s%s%s",s1,s2,stag);
			strcpy(s,s1);
			strcat(s,s2);
			strcpy(s0,s);
			for(t=0;strcmp(s,stag)!=0;t++)
			{
				for(j=0;j<n;j++)
					s1[j]=s[j];
				for(i=0;i<n;i++,j++)
					s2[i]=s[j];
				for(i=0,j=0;i<n;i++,j+=2)
				{
					s[j]=s2[i];
					s[j+1]=s1[i];
				}
				if(strcmp(s0,s)==0)
				{
					t=-1;
					break;
				}
			}
			printf("%d %d\n",k,t);
		}
	}
	return 0;
} 

Problem H
POJ3414
DFS六种可能性,用数组保存每次的操作代号最后输出,一开始用string直接保存的,结果TLE了。。。
#include<string>
#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a,b,c,res;
char pa[10010],pp[10010];
bool flag,vis[105][105];
void dfs(int x,int y,int dep)
{
	if(dep>res)
		return;
	if(x==c||y==c)
	{
		if(dep<res)
		{
			flag=1;
			res=dep;
			for(int i=0;i<res;i++)
				pa[i]=pp[i];
		}
		return;
	}
	if(x<a&&!vis[a][y])//FILL 1
	{
		vis[a][y]=1;
		pp[dep]='f';
		dfs(a,y,dep+1);
		vis[a][y]=0;
	}
	if(y<b&&!vis[x][b])//FILL 2
	{
		vis[x][b]=1;
		pp[dep]='F';
		dfs(x,b,dep+1);
		vis[x][b]=0;
	}
	if(x>0&&!vis[0][y])//DROP 1
	{
		vis[0][y]=1;
		pp[dep]='d';
		dfs(0,y,dep+1);
		vis[0][y]=0;
	}
	if(y>0&&!vis[x][0])//DROP 2
	{
		vis[x][0]=1;
		pp[dep]='D';
		dfs(x,0,dep+1);
		vis[x][0]=0;
	}
	if(x>0&&y<b)//POUR(1,2)
	{
		int t=min(x,b-y);
		if(!vis[x-t][y+t])
		{
			vis[x-t][y+t]=1;
			pp[dep]='p';
			dfs(x-t,y+t,dep+1);
			vis[x-t][y+t]=0;
		}
	}
	if(y>0&&x<a)//POUR(2,1)
	{
		int t=min(y,a-x);
		if(!vis[x+t][y-t])
		{
			vis[x+t][y-t]=1;
			pp[dep]='P';
			dfs(x+t,y-t,dep+1);
			vis[x+t][y-t]=0;
		}
	}
	return;
}
int main()
{
	int i;
	while(scanf("%d%d%d",&a,&b,&c)!=EOF)
	{
		memset(vis,0,sizeof(vis));
		vis[0][0]=1;
		flag=0;
		res=0x7fffffff;
		dfs(0,0,0);
		if(flag)
		{
			printf("%d\n",res);
			for(int i=0;i<res;i++)
			{
				if(pa[i]=='f')
					printf("FILL(1)\n");
				if(pa[i]=='F')
					printf("FILL(2)\n");
				if(pa[i]=='d')
					printf("DROP(1)\n");
				if(pa[i]=='D')
					printf("DROP(2)\n");
				if(pa[i]=='p')
					printf("POUR(1,2)\n");
				if(pa[i]=='P')
					printf("POUR(2,1)\n");
			}
		}
		else printf("impossible\n");
	}
	return 0;
}
Problem I
FZU2150
从两个地方放火,两处可以是同一地点,问最短需要多少时间才能让他们玩上XXOO游戏(可见 福州大学的Acmer啧啧啧啧)。。。。。。。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#define INF 0x7fffffff
using namespace std;
int dir_x[4]={0,0,1,-1};
int dir_y[4]={1,-1,0,0};
int n,m,tmin,tmax;
int map[11][11],vis[11][11];
int visit[11][11][11][11]; 
struct state
{
	int x,y;
	int t;//time	
};
int inrange(int x,int y)
{
	if(x<1||x>n||y<1||y>m)
		return 1;
	return 0;
}
void bfs(int x1,int y1,int x2,int y2)
{
	queue<state>s;
	int i,j;
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			vis[i][j]=map[i][j];
	state p;
	p.x=x1;
	p.y=y1;
	p.t=0;
	s.push(p);
	p.x=x2;
	p.y=y2;
	p.t=0;
	s.push(p);
	vis[x1][y1]=vis[x2][y2]=0;
	while(!s.empty())
	{
		state q;
		q=s.front();
		s.pop();
		tmax=q.t; 
		for(i=0;i<4;i++)
		{
			state now;
			now.x=q.x+dir_x[i];
			now.y=q.y+dir_y[i];
			now.t=q.t+1;
			if(!inrange(now.x,now.y)&&vis[now.x][now.y])
			{
				vis[now.x][now.y]=0;
				s.push(now);
			}
		}
	}
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
		{
			if(vis[i][j])
				tmax=INF;
		}
}
int main()
{
	 int i,j,t,p,q,k;
	 char c;
	 while(scanf("%d",&t)!=EOF)
	 {
	 	for(k=1;k<=t;k++)
	 	{
	 		scanf("%d%d",&n,&m);
	 		getchar();
	 		for(i=1;i<=n;i++)
	 		{
	 			for(j=1;j<=m;j++)
	 			{
	 				cin>>c;
	 				if(c=='#')
	 					map[i][j]=1;
	 				else 
	 					map[i][j]=0;
	 			}
	 		}
	 		tmin=INF;
	 		memset(visit,0,sizeof(visit));
	 		for(i=1;i<=n;i++)
	 			for(j=1;j<=m;j++)
	 				for(p=1;p<=n;p++)
	 					for(q=1;q<=m;q++)
	 					{
	 						if(map[i][j]&&map[p][q]&&!visit[p][q][i][j])
	 						{
	 							visit[i][j][p][q]=1;
	 							bfs(i,j,p,q);
	 							tmin=min(tmin,tmax);
	 						}
	 					}
	 		if(tmin==INF)
	 			printf("Case %d: -1\n",k);
	 		else 
	 			printf("Case %d: %d\n",k,tmin);
	 	}
	 }
	 return 0;
} 

Problem J
UVA11624
先BFS一次每一块着火的最段时间,再对JOE进行一次BFS,如果JOE到达某块的时间比它的着火时间短加入队列,
注意初始着火点可能有多个
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
#define INF 0x7fffffff-10 
using namespace std;
int dir_x[4]={1,-1,0,0};
int dir_y[4]={0,0,1,-1};
int c,r,fx[1000005],fy[1000005],jx,jy,cnt;
int tim[1005][1005];
bool vis[1005][1005];
bool map[1005][1005];
struct state
{
	int x,y;
	int t;
};
int inrange(int x,int y)
{
	if(x>r||x<1||y>c||y<1)
		return 0;
	return 1;
}
void Fbfs()
{
	int i,j;
	queue<state>s;
	state p;
	memset(vis,0,sizeof(vis));
	for(i=0;i<=cnt-1;i++)
	{
		p.x=fx[i];
		p.y=fy[i];
		p.t=0;
		s.push(p);
		vis[fx[i]][fy[i]]=1; 
	}
	while(!s.empty())
	{
		p=s.front();
		s.pop();
		for(i=0;i<4;i++)
		{
			state now;
			now.x=p.x+dir_x[i];
			now.y=p.y+dir_y[i];
			if(inrange(now.x,now.y)&&!vis[now.x][now.y]&&!map[now.x][now.y]&&tim[now.x][now.y]>p.t+1)
			{
				vis[now.x][now.y]=1;
			//	if(time[now.x][now.y]>now.t)
				now.t=p.t+1;
				tim[now.x][now.y]=now.t;
				s.push(now);
			}
		} 
	} 
}
void Jbfs()
{
	int i,j;
	state p;
	queue<state>s;
	p.x=jx;
	p.y=jy;
	p.t=0;
	s.push(p);
	memset(vis,0,sizeof(vis));
	vis[jx][jy]=1;
	while(!s.empty())
	{
		p=s.front();
		s.pop();
		if(p.x==r||p.y==c||p.x==1||p.y==1)
		{
			printf("%d\n",p.t+1);
			return;
		}
		for(i=0;i<4;i++)
		{
			state now;
			now.x=p.x+dir_x[i];
			now.y=p.y+dir_y[i];
			now.t=p.t+1;
			if(now.t<tim[now.x][now.y]&&!vis[now.x][now.y]&&inrange(now.x,now.y)&&!map[now.x][now.y])
			{
				vis[now.x][now.y]=1;
				s.push(now);
			}
		}
	}
	printf("IMPOSSIBLE\n");
}
int main()
{
	int n,i,j;
	char ch;
	while(scanf("%d",&n)!=EOF)
	{
		while(n--)
		{
			cnt=0;
			scanf("%d%d",&r,&c);
			for(i=1;i<=r;i++)
				for(j=1;j<=c;j++)
				{
					cin>>ch;
					tim[i][j]=INF; 
					if(ch=='J')
					{
						jx=i;
						jy=j;
						map[i][j]=0;
					}
					if(ch=='F')
					{
						fx[cnt]=i;
						fy[cnt++]=j;
						map[i][j]=1;
						tim[i][j]=0;
					}
					if(ch=='#')
						map[i][j]=1;
					if(ch=='.')
						map[i][j]=0;
				}
			Fbfs();
			Jbfs();
		}
	}
	return 0;
}
Problem K
POJ3984
结构体中用,pre变量保存当前点之前的位置,用数组模拟队列
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dir_x[4]={0,0,1,-1};
int dir_y[4]={1,-1,0,0};
int visit[6][6];
struct point
{
	int x,y;
	int pre;//记录之前的位置 pre=previous
}queue[100];
bool inrange(int x,int y)
{
	if(x>4||x<0||y>4||y<0)
		return false;
	return true;
}
void print(int i)
{
	if(queue[i].pre!=-1)
	{
		print(queue[i].pre);
		printf("(%d, %d)\n",queue[i].x,queue[i].y);
	}
} 
void bfs()
{
	int a,b;
	int front,rear;
	front=0;
	rear=1;
	queue[front].x=0;
	queue[front].y=0;
	queue[front].pre=-1;//(0, 0)之前的位置记为-1
	while(front<rear)
	{
		for(int i=0;i<=3;i++)
		{
			a=queue[front].x+dir_x[i];
			b=queue[front].y+dir_y[i];
			if(!inrange(a,b)||visit[a][b])
				continue;
			else 
			{
				visit[a][b]=1;
				queue[rear].x=a;
				queue[rear].y=b;
				queue[rear].pre=front;
				rear++;
			}
			if(a==4&&b==4)
			{
				printf("(0, 0)\n");
				print(front);
				printf("(4, 4)\n");
			}
		}
		front++;
	} 
} 
int main()
{
	int i,j;
	while(scanf("%d",&visit[0][0])!=EOF)
	{
		memset(visit,0,sizeof(visit));
		for(i=1;i<=4;i++)
			scanf("%d",&visit[0][i]);
		for(i=1;i<=4;i++)
			for(j=0;j<=4;j++)
				scanf("%d",&visit[i][j]);
		bfs();
	}
	return 0;
} 
Problem L
HDU1241
连通块问题,DFS解决
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int dir_x[8]={0,0,1,-1,1,1,-1,-1};
int dir_y[8]={1,-1,0,0,1,-1,1,-1};
int map[105][105];
int m,n;
void dfs(int x,int y)
{
	map[x][y]=0;
	for(int i=0;i<=7;i++)
	{
		int a=x+dir_x[i];
		int b=y+dir_y[i];
		if(a<1||b<1||b>n||a>m||map[a][b]==0)
			continue;
		else
			dfs(a,b);
	}
	return;
}
int main()
{
	int ans,i,j;
	char c;
	while(scanf("%d %d",&m,&n)!=EOF&&(m||n))
	{
		getchar();
		for(i=1;i<=m;i++)
		{
			for(j=1;j<=n;j++)
			{
				cin>>c;
				if(c=='@')
					map[i][j]=1;
				else
					map[i][j]=0;
			}
		}
	//	for(i=1;i<=m;i++)
		//{
		//	for(j=1;j<=n;j++)
		//		printf("%d",map[i][j]);
		//	printf("\n");
	//	}
		ans=0;
		for(i=1;i<=m;i++)
			for(j=1;j<=n;j++)
				if(map[i][j])
				{
					dfs(i,j);
					ans++;
				}
		printf("%d\n",ans);
	}
	return 0;
}

Problem M
HDU1495
倒可乐, 主要就是麻烦。。。分类讨论,结构体里每个变量都要赋值,找了好久的bug。。。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring> 
#include<queue>
using namespace std;
int visit[300][300];
int f[3];
struct state
{
	int x[3];
	int step;//倒的次数; 
};
queue<state>s;
void bfs()
{
	int i,j;
	state p;
	p.x[0]=f[0];
	p.x[1]=0;
	p.x[2]=0;
	p.step=0;
	s.push(p);
	while(!s.empty())
	{
		state q;
		q=s.front();
		s.pop();
		if((q.x[0]==f[0]/2&&q.x[1]==f[0]/2)||(q.x[0]==f[0]/2&&q.x[2]==f[0]/2)||(q.x[2]==f[0]/2&&q.x[1]==f[0]/2))//判断是否满足条件 
		{
			printf("%d\n",q.step);
			return;
		}
		for(i=0;i<=2;i++)
		{
			state y;
			if(q.x[i]>0)//将i的可乐倒入j中 
			{
				for(j=0;j<=2;j++)
				{
					if(i==j)
						continue;
					if(q.x[i]+q.x[j]>f[j])
					{
						y.x[i]=q.x[i]-(f[j]-q.x[j]);
						y.x[j]=f[j];
						y.x[3-i-j]=q.x[3-i-j];
					}
					else
					{
						y.x[i]=0;
						y.x[j]=q.x[i]+q.x[j];
						y.x[3-i-j]=q.x[3-i-j];
					}
					int a,b;
					a=y.x[1];
					b=y.x[2];
					if(a>=0&&b>=0&&a<=f[1]&&b<=f[2]&&visit[a][b]==0)
					{
						visit[a][b]=1;
						y.step=q.step+1;
						s.push(y);
					}
				}
			}		
		}
	}
	printf("NO\n");
}
int main()
{
	while(scanf("%d%d%d",&f[0],&f[1],&f[2])!=EOF&&(f[0]||f[1]||f[2]))
	{
		if(f[0]%2)
		{
			printf("NO\n");
			continue;
		}
		if(f[1]==f[2])
		{
			printf("1\n");
			continue;
		}
		else
		{
			while(!s.empty())
				s.pop();
			memset(visit,0,sizeof(visit));
			visit[0][0]=true;
			bfs();
		}
	}
	return 0;
}

Problem N
HDU2612
审题,两人时间的总和最少而不是俩人的时间只算一次,两次BFS即可,最后取最小时间的和
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring> 
#define INF 0x7fffffff
using namespace std;
int dir_x[4]={0,0,1,-1};
int dir_y[4]={1,-1,0,0};
char map[205][205];
int ans1[205][205];
int ans2[205][205]; 
int visit[205][205];
int x1,x2,y1,y2,m,n,mint;
struct state
{
	int x,y;
	int step;
};
int inrange(int x,int y)
{
	if(x<1||x>n||y<1||y>m)
		return 0;
	return 1;
}
void bfs(int x,int y,int ans[205][205])
{
	int i,j;
	memset(visit,0,sizeof(visit));
	memset(ans,0,sizeof(ans));
	queue<state>s;
	state p;
	p.x=x;
	p.y=y;
	p.step=0;
	s.push(p);
	visit[x][y]=1;
	while(!s.empty())
	{
		state q;
		q=s.front();
		s.pop();
		if(map[q.x][q.y]=='@')
		{
			ans[q.x][q.y]=q.step;
		}
		for(i=0;i<4;i++)
		{
			state w;
			w.x=q.x+dir_x[i];
			w.y=q.y+dir_y[i];
			w.step=q.step+1;
			if(inrange(w.x,w.y)&&!visit[w.x][w.y]&&map[w.x][w.y]!='#')
			{
				s.push(w);
				visit[w.x][w.y]=1;
			}
		}
	}
}
int main()
{
	int i,j;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		getchar();
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=m;j++)
			{
				cin>>map[i][j];
				if(map[i][j]=='Y')
				{
					x1=i;
					y1=j;
				}
				if(map[i][j]=='M')
				{
					x2=i;
					y2=j;
				}
			}
		}
		bfs(x1,y1,ans1);
		bfs(x2,y2,ans2);
		mint=INF;
	//	for(i=1;i<=n;i++)
	//	{
		//	for(j=1;j<=m;j++)
		//	{
		//		cout<<ans2[i][j];
		//	}
		//	printf("\n");
	//	}
		for(i=1;i<=n;i++)
			for(j=1;j<=m;j++)
			{
				if(ans1[i][j]&&ans2[i][j]&&map[i][j]=='@')
					mint=min(mint,ans1[i][j]+ans2[i][j]);
			}
		printf("%d\n",mint*11);
	}
	return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值