专题一、简单搜索 - Virtual Judge

很久以前刷完了Virtual Judge上的简单搜索专题,现总结如下:

POJ 1321

由于题目的数据范围比较小,可以直接dfs暴力。读入时记录每个空位的位置,保存在pX[]以及pY[]数组中。暴力的时候统计当前处理第几个空格以及当前处理到了第几行即可。

#include <iostream>
#include <memory.h>

using namespace std;

const int MAX = 128;

long long ans;
int N, K, nCnt;
bool pUsed[MAX];
int pX[MAX], pY[MAX];
int pRow[MAX], pCol[MAX];

void dfs(int x, int y);

int main()
{
	char dwTmp;
	while(cin >> N >> K)
	{
		if(N == -1 && K == -1) { break; }
		nCnt = 0; ans = 0;
		for(int i = 1; i <= N; i++)
		{
			for(int j = 1; j <= N; j++)
			{
				cin >> dwTmp;
				if(dwTmp == ‘#‘)
				{ nCnt++; pX[nCnt] = i; pY[nCnt] = j; }
			}
			cin.ignore();
		}
		memset(pRow, 0, sizeof(pRow));
		memset(pCol, 0, sizeof(pCol));
		memset(pUsed, false, sizeof(pUsed));
		dfs(1, 0);
		cout << ans << endl;
	}
	return 0;
}

void dfs(int x, int y)
{
	if(y == K)
	{ ans++; }
	else
	{
		for(int i = x; i <= nCnt; i++)
		{
			if(!(pUsed[i] || pRow[pX[i]] || pCol[pY[i]]))
			{
				pRow[pX[i]]++; pCol[pY[i]]++;
				pUsed[i] = true;
				dfs(i + 1, y + 1);
				pUsed[i] = false;
				pRow[pX[i]]--; pCol[pY[i]]--;
			}
		}
	}
}

  

POJ 2251

这是一个三维迷宫,对立体空间的六个方向进行bfs即可。

#include <iostream>
#include <memory.h>
#include <string>
#include <queue>

using namespace std;

const int MAX = 32;

const int dx[] = { 1, -1, 0, 0, 0, 0 };
const int dy[] = { 0, 0, 1, -1, 0, 0 };
const int dz[] = { 0, 0, 0, 0, 1, -1 };

struct Point
{
	Point(int _x = 0, int _y = 0, int _z = 0, int _ans = 0)
	{ x = _x; y = _y; z = _z; ans = 0; }

	int x, y, z, ans;
};

queue<Point> Q;
Point Start, End;
int pMaze[MAX][MAX][MAX];
bool pVisited[MAX][MAX][MAX];

int main()
{
	int L, R, C;
	string strTmp;
	while(cin >> L >> R >> C)
	{
		if(L == 0 && R == 0 && C == 0) { break; }
		while(!Q.empty()) { Q.pop(); }
		for(int i = 1; i <= L; i++)
		{
			for(int j = 1; j <= R; j++)
			{
				cin >> strTmp;
				for(int k = 1; k <= C; k++)
				{
					if(strTmp[k - 1] == ‘S‘) { pMaze[i][j][k] = 0; Start = Point(i, j, k); }
					else if(strTmp[k - 1] == ‘E‘) { pMaze[i][j][k] = 0; End = Point(i, j, k); }
					else if(strTmp[k - 1] == ‘.‘) { pMaze[i][j][k] = 0; }
					else if(strTmp[k - 1] == ‘#‘) { pMaze[i][j][k] = 1; }
				}
			}
		}
		Q.push(Start);
		bool bFlag = false;
		memset(pVisited, false, sizeof(pVisited));
		pVisited[Start.x][Start.y][Start.z] = true;
		while(!Q.empty())
		{
			Point Now = Q.front(); Q.pop();
			if(Now.x == End.x && Now.y == End.y && Now.z == End.z) { cout << "Escaped in " << Now.ans << " minute(s)." << endl; bFlag = true; break; }
			for(int i = 0; i < 6; i++)
			{
				Point Next;
				Next.x = Now.x + dx[i]; Next.y = Now.y + dy[i]; Next.z = Now.z + dz[i]; Next.ans = Now.ans + 1;
				if(Next.x >= 1 && Next.x <= L && Next.y >= 1 && Next.y <= R && Next.z >= 1 && Next.z <= C &&
					pMaze[Next.x][Next.y][Next.z] == 0 && !pVisited[Next.x][Next.y][Next.z])
				{
					pVisited[Next.x][Next.y][Next.z] = true;
					Q.push(Next);
				}
			}
		}
		if(!bFlag) { cout << "Trapped!" << endl; }
	}
	return 0;
}

  

POJ 3278

同样是bfs,一共三种状态进行转移。

#include <iostream>
#include <memory.h>
#include <queue>

using namespace std;

const int MAX = 1024000;

struct Pos
{
	Pos(int _x = 0, int _ans = 0)
	{ x = _x; ans = _ans; }

	int x, ans;
};

queue<Pos> Q;
bool pVisited[MAX];

int main()
{
	int N, K;
	while(cin >> N >> K)
	{
		memset(pVisited, false, sizeof(pVisited));
		while(!Q.empty()) { Q.pop(); }
		Q.push(Pos(N, 0)); pVisited[N] = true;
		while(!Q.empty())
		{
			Pos Now = Q.front(); Q.pop();
			if(Now.x == K) { cout << Now.ans << endl; break; }
			if(Now.x * 2 >= 0 && Now.x * 2 < MAX && !pVisited[Now.x * 2])
			{
				Q.push(Pos(Now.x * 2, Now.ans + 1));
				pVisited[Now.x * 2] = true;
			}
			if(Now.x - 1 >= 0 && Now.x - 1 < MAX && !pVisited[Now.x - 1])
			{
				Q.push(Pos(Now.x - 1, Now.ans + 1));
				pVisited[Now.x - 1] = true;
			}
			if(Now.x + 1 >= 0 && Now.x + 1 < MAX && !pVisited[Now.x + 1])
			{
				Q.push(Pos(Now.x + 1, Now.ans + 1));
				pVisited[Now.x + 1] = true;
			}
		}
	}
	return 0;
}

  

POJ 3279

考虑到第一行的状态确定以后,后面的N - 1行的状态就确定了,因此只需要枚举第一行,由于数据范围比较小,所以使用二进制状态压缩即可。

#include <iostream>
#include <memory.h>

using namespace std;

const int MAX = 32;

const int dx[] = { 1, -1, 0, 0 };
const int dy[] = { 0, 0, 1, -1 };

int M, N;
int pMap[MAX][MAX];
int pAns[MAX][MAX], pTmp[MAX][MAX];

int Solve();
int IsFlip(int x, int y);

int main()
{
	while(cin >> M >> N)
	{
		int ans = 2147483647;
		for(int i = 1; i <= M; i++)
		{
			for(int j = 1; j <= N; j++)
			{ cin >> pMap[i][j]; }
		}
		for(int i = 0; i < (1 << N); i++)
		{
			memset(pTmp, 0, sizeof(pTmp));
   			for(int j = 1; j <= N; j++)
   			{
   				if(i & (1 << j - 1))
   				{ pTmp[1][j] = 1; }
   			}
   			int nTmp = Solve();
   			if(nTmp == -1) { continue; }
			if(nTmp < ans)
			{
				ans = nTmp;
				memcpy(pAns, pTmp, sizeof(pTmp));
			}
		}
		if(ans != 2147483647)
		{
			for(int i = 1; i <= M; i++)
			{
				for(int j = 1; j <= N; j++)
				{
					cout << pAns[i][j];
					if(j != N) { cout << " "; }
				}
				cout << endl;
			}
		}
		else { cout << "IMPOSSIBLE" << endl; }
	}
	return 0;
}

int Solve()
{
	int nRet = 0;
	for(int i = 2; i <= M; i++)
	{
		for(int j = 1; j <= N; j++)
		{
			if(IsFlip(i - 1, j)) { pTmp[i][j] = 1; }
		}
	}
	for(int i = 1; i <= N; i++)
	{
		if(IsFlip(M, i)) { return -1; }
	}
	for(int i = 1; i <= M; i++)
	{
		for(int j = 1; j <= N; j++)
		{
			nRet += pTmp[i][j];
		}
	}
	return nRet;
}

int IsFlip(int x, int y)
{
	int nRet = pTmp[x][y];
	for(int i = 0; i < 4; i++)
	{
		int nx = x + dx[i];
		int ny = y + dy[i];
		if(nx >= 1 && nx <= M && ny >= 1 && ny <= N)
		{ nRet += pTmp[nx][ny]; }
	}
	nRet += pMap[x][y];
	return nRet & 1;
}

  

POJ 1426

这道题目也是一道bfs,只需要记录每次遍历到的结果tmp % N,同时保存已选取的数字的内容,最后判断已选取的数字的长度是否符合题目的要求。

#include <iostream>
#include <memory.h>
#include <string>
#include <queue>

using namespace std;

const int MAX = 256;

const int d[] = { 0, 1 };

struct Num
{
	Num(int _nNum = 1, string _ans = "1")
	{
		nNum = _nNum;
		ans = _ans;
	}

	int nNum;
	string ans;
};

int N;
bool pVisited[MAX];
queue<Num> Q;

int main()
{
	while(cin >> N)
	{
		if(N == 0) { break; }
		else
		{
			while(!Q.empty()) { Q.pop(); }
			memset(pVisited, false, sizeof(pVisited));
   			Q.push(Num(1)); pVisited[1 % N] = true;
   			while(!Q.empty())
   			{
   				Num Now = Q.front(); Q.pop();
				if(Now.nNum % N == 0) { cout << Now.ans << endl; break; }
				for(int i = 0; i < 2; i++)
   				{
   					Num Next = Now;
					if(!pVisited[(Now.nNum * 10 + d[i]) % N])
					{
						pVisited[(Now.nNum * 10 + d[i]) % N] = true;
						Q.push(Num((Now.nNum * 10 + d[i]) % N, Now.ans + (char)(d[i] + ‘0‘)));
					}
   				}
   			}
		}
	}
	return 0;
}

  

POJ 3126

bfs水题。

#include <iostream>
#include <memory.h>
#include <string>
#include <queue>
#include <set>

using namespace std;

const int MAX = 10240;

struct Prime
{
	Prime(int _x = 0, int _ans = 0)
	{ x = _x; ans = _ans; }

	int x, ans;
};

set<int> S;
queue<Prime> Q;
bool pVisited[MAX];

int Change(int x, int y, int z);

int main()
{
	for(int i = 1000; i <= 9999; i++)
	{
		bool bFlag = true;
		for(int j = 2; j * j <= i; j++)
		{
			if(i % j == 0) { bFlag = false; }
		}
		if(bFlag) { S.insert(i); }
	}
	int N, s, e;
	while(cin >> N)
	{
		for(int i = 1; i <= N; i++)
		{
			while(!Q.empty()) { Q.pop(); }
			memset(pVisited, false, sizeof(pVisited));
			cin >> s >> e;
			Q.push(Prime(s, 0)); pVisited[s] = true;
			while(!Q.empty())
			{
				Prime Now = Q.front(); Q.pop();
				if(Now.x == e) { cout << Now.ans << endl; break; }
				for(int i = 0; i < 4; i++)
				{
					for(int j = 0; j <= 9; j++)
					{
						int nNext = Change(Now.x, i, j);
						if(S.count(nNext) && !pVisited[nNext])
						{
							Q.push(Prime(nNext, Now.ans + 1));
							pVisited[nNext] = true;
						}
					}
   				}
			}
		}
	}
	return 0;
}

int Change(int x, int y, int z)
{
	int nTmp = 1;
	while(y--) { nTmp *= 10; }
	x -= x / nTmp % 10 * nTmp;
	x += z * nTmp;
	return x;
}

  

POJ 3087

模拟整个过程即可,如果出现与初始情况相同的情形,就说明无解。

#include <iostream>
#include <string>

using namespace std;

int main()
{
	int N, C;
	bool bFlag;
	string SA, SB, S, Init;
	cin >> N;
	for(int i = 1; i <= N; i++)
	{
		cin >> C >> SA >> SB >> S;
		int nCnt = 0; Init = ""; bFlag = false;
 		while(1)
		{
			nCnt++;
			string ans = "";
			for(int j = 0; j < SA.size(); j++)
			{
				ans += SB[j];
				ans += SA[j];
			}
			if(Init == "") { Init = ans; }
			SA = ans.substr(0, C);
			SB = ans.substr(C, C);
			if(nCnt != 1 && ans == Init) { break; }
			if(ans == S) { cout << i << " " << nCnt << endl; bFlag = true; break; }
		}
		if(!bFlag) { cout << i << " -1" << endl; }
	}
	return 0;
}

  

POJ 3414

bfs水题。处理好倒水的过程即可。

#include <iostream>
#include <memory.h>
#include <string>
#include <queue>

using namespace std;

const int MAX = 128;

struct Pots
{
	Pots(int _A = 0, int _B = 0)
	{
		A = _A; B = _B;
		while(!pOpt.empty()) { pOpt.pop(); }
	}

	int A, B;
	queue<string> pOpt;
};

int A, B, C;
bool pVisited[MAX][MAX];
queue<Pots> Q;

Pots Opt(Pots Now, int k);
Pots Fill(Pots Now, int x);
Pots Drop(Pots Now, int x);
Pots Pour(Pots Now, int x);

int main()
{
	bool bFlag;
	while(cin >> A >> B >> C)
	{
		bFlag = false;
		while(!Q.empty()) { Q.empty(); }
		memset(pVisited, false, sizeof(pVisited));
		Q.push(Pots(0, 0)); pVisited[0][0] = true;
		while(!Q.empty())
		{
			Pots Now = Q.front(); Q.pop();
			if(Now.A == C || Now.B == C)
			{
				cout << Now.pOpt.size() << endl;
				while(!Now.pOpt.empty())
				{
					cout << Now.pOpt.front() << endl;
					Now.pOpt.pop();
				}
				bFlag = true;
				break;
			}
			for(int i = 0; i < 6; i++)
			{
				Pots Next = Opt(Now, i);
				if(!pVisited[Next.A][Next.B])
				{
					Q.push(Next);
					pVisited[Next.A][Next.B] = true;
				}
			}
		}
		if(!bFlag) { cout << "impossible" << endl; }
	}
	return 0;
}

Pots Opt(Pots Now, int k)
{
	switch(k)
	{
		case 0:
			return Fill(Now, 0);
		case 1:
			return Fill(Now, 1);
		case 2:
			return Drop(Now, 0);
		case 3:
			return Drop(Now, 1);
		case 4:
			return Pour(Now, 0);
		case 5:
			return Pour(Now, 1);
	}
}

Pots Fill(Pots Now, int x)
{
	if(x == 0) { Now.A = A; Now.pOpt.push("FILL(1)"); }
	else { Now.B = B; Now.pOpt.push("FILL(2)"); }
	return Now;
}

Pots Drop(Pots Now, int x)
{
	if(x == 0) { Now.A = 0; Now.pOpt.push("DROP(1)"); }
	else { Now.B = 0; Now.pOpt.push("DROP(2)"); }
	return Now;
}

Pots Pour(Pots Now, int x)
{
	if(x == 0)
	{
		Now.B += Now.A;
		if(Now.B > B) { Now.A = Now.B - B; Now.B = B; }
		else { Now.A = 0; }
		Now.pOpt.push("POUR(1,2)");
	}
	else
	{
		Now.A += Now.B;
		if(Now.A > A) { Now.B = Now.A - A; Now.A = A; }
		else { Now.B = 0; }
		Now.pOpt.push("POUR(2,1)");
	}
	return Now;
}

  

FZU 2150

暴力枚举两个起点,然后bfs。

#include <iostream>
#include <memory.h>
#include <string>
#include <queue>

using namespace std;

const int MAX = 16;

const int dx[] = { 1, -1, 0, 0 };
const int dy[] = { 0, 0, 1, -1 };

struct Pos
{
	Pos(int _x, int _y, int _ans)
	{ x = _x; y = _y; ans = _ans; }

	int x, y, ans;
};

int T, N, M;
int pMap[MAX][MAX];
bool pVisited[MAX][MAX];
queue<Pos> Q;

bool Check();
int Bfs(Pos A, Pos B);

int main()
{
	string strTmp;
	cin >> T;
	for(int k = 1; k <= T; k++)
	{
		cin >> N >> M;
		int ans = 2147483647;
		bool bFlag = false;
		for(int i = 1; i <= N; i++)
		{
			cin >> strTmp;
			for(int j = 1; j <= M; j++)
			{
				if(strTmp[j - 1] == ‘.‘) { pMap[i][j] = 1; }
				else { pMap[i][j] = 0; }
			}
		}
		for(int i = 1; i <= N; i++)
		{
			for(int j = 1; j <= M; j++)
			{
				for(int p = 1; p <= N; p++)
				{
					for(int q = 1; q <= M; q++)
					{
						if(pMap[i][j] || pMap[p][q]) { continue; }
						int nTmp = Bfs(Pos(i, j, 0), Pos(p, q, 0));
						if(Check()) { ans = min(ans, nTmp); bFlag = true; }
					}
				}
			}
		}
		cout << "Case " << k << ": ";
		if(bFlag) { cout << ans << endl; }
		else { cout << -1 << endl; }
	}
	return 0;
}

int Bfs(Pos A, Pos B)
{
	int nRet = 0;
	while(!Q.empty()) { Q.pop(); }
	memset(pVisited, false, sizeof(pVisited));
	Q.push(A); pVisited[A.x][A.y] = true;
	Q.push(B); pVisited[B.x][B.y] = true;
	while(!Q.empty())
	{
		Pos Now = Q.front(); Q.pop();
		nRet = max(nRet, Now.ans);
		for(int i = 0; i < 4; i++)
		{
			Pos Next = Now; Next.ans++;
			Next.x += dx[i]; Next.y += dy[i];
			if(Next.x >= 1 && Next.x <= N &&
				Next.y >= 1 && Next.y <= M &&
				!pVisited[Next.x][Next.y] && !pMap[Next.x][Next.y])
			{
				Q.push(Next);
				pVisited[Next.x][Next.y] = true;
			}
		}
	}
	return nRet;
}

bool Check()
{
	for(int i = 1; i <= N; i++)
	{
		for(int j = 1; j <= M; j++)
		{
			if(!pMap[i][j] && !pVisited[i][j])
			{ return false; }
		}
	}
	return true;
}

  

UVa 11624

注意可能有多个点起火,设定一个全局时间量,用来控制人以及火的运动顺序,先处理火,再处理人。然后就是bfs水题。

#include <iostream>
#include <memory.h>
#include <queue>

using namespace std;

const int MAX = 1024;

const int dx[] = { 1, -1, 0, 0 };
const int dy[] = { 0, 0, 1, -1 };

struct Pos
{
	Pos(int _x = 0, int _y = 0, int _ans = 0)
	{ x = _x; y = _y; ans = _ans; }

	int x, y, ans;
};

int T, R, C;
int pMap[MAX][MAX];
bool pVJ[MAX][MAX], pVF[MAX][MAX];
queue<Pos> J, F;

int main()
{
	string strTmp;
	cin >> T;
	for(int k = 1; k <= T; k++)
	{
		cin >> R >> C;
		bool bFlag = false;
		while(!J.empty()) { J.pop(); }
		while(!F.empty()) { F.pop(); }
		memset(pVJ, false, sizeof(pVJ));
		memset(pVF, false, sizeof(pVF));
		for(int i = 1; i <= R; i++)
		{
			cin >> strTmp;
			for(int j = 1; j <= C; j++)
			{
				if(strTmp[j - 1] == ‘#‘) { pMap[i][j] = 1; }
				else { pMap[i][j] = 0; }
				if(strTmp[j - 1] == ‘J‘) { J.push(Pos(i, j)); pVJ[i][j] = true; }
				if(strTmp[j - 1] == ‘F‘) { F.push(Pos(i, j)); pVF[i][j] = true; }
			}
		}
		int nTime = 0;
		while(!J.empty())
		{
			while(!F.empty() && F.front().ans <= nTime)
			{
				Pos FN = F.front(); F.pop();
				for(int i = 0; i < 4; i++)
				{
					Pos Next = FN; Next.ans++;
					Next.x += dx[i]; Next.y += dy[i];
					if(Next.x >= 1 && Next.x <= R && Next.y >= 1 && Next.y <= C &&
						!pMap[Next.x][Next.y] && !pVF[Next.x][Next.y])
					{
						F.push(Next);
						pVF[Next.x][Next.y] = true;
					}
				}
			}
			while(!J.empty() && J.front().ans  <= nTime)
			{
				Pos JN = J.front(); J.pop();
				if(JN.x == 1 || JN.x == R || JN.y == 1 || JN.y == C) { cout << JN.ans + 1 << endl; bFlag = true; break; }
				for(int i = 0; i < 4; i++)
				{
					Pos Next = JN; Next.ans++;
					Next.x += dx[i]; Next.y += dy[i];
					if(Next.x >= 1 && Next.x <= R && Next.y >= 1 && Next.y <= C &&
						!pMap[Next.x][Next.y] && !pVF[Next.x][Next.y] && !pVJ[Next.x][Next.y])
					{
						J.push(Next);
						pVJ[Next.x][Next.y] = true;
					}
				}
			}
			if(bFlag) { break; }
			nTime++;
		}
		if(!bFlag) { cout << "IMPOSSIBLE" << endl; }
	}
	return 0;
}

  

POJ 3984

bfs水题。

#include <iostream>
#include <memory.h>
#include <queue>

using namespace std;

const int MAX = 8;

const int dx[] = { 1, -1, 0, 0 };
const int dy[] = { 0, 0, 1, -1 };

struct Pos
{
	Pos(int _x = 0, int _y = 0)
	{ x = _x; y = _y; }
	int x, y;
};

struct State
{
	State(int _x = 0, int _y = 0)
	{
		Now = Pos(_x, _y);
		while(!Ans.empty()) { Ans.pop(); }
	}

	Pos Now;
	queue<Pos> Ans;
};

int pMap[MAX][MAX];
bool pVisited[MAX][MAX];
queue<State> Q;

int main()
{
	for(int i = 1; i <= 5; i++)
	{
		for(int j = 1; j <= 5; j++)
		{ cin >> pMap[i][j]; }
	}
	while(!Q.empty()) { Q.pop(); }
	memset(pVisited, false, sizeof(pVisited));
	Q.push(State(1, 1)); pVisited[1][1] = true;
	while(!Q.empty())
	{
		State Now = Q.front(); Q.pop();
		if(Now.Now.x == 5 && Now.Now.y == 5)
		{
			while(!Now.Ans.empty())
			{
				Pos Cur = Now.Ans.front();
				cout << "(" << Cur.x - 1 << ", " << Cur.y - 1 << ")" << endl;
				Now.Ans.pop();
			}
			cout << "(4, 4)" << endl;
			break;
		}
		for(int i = 0; i < 4; i++)
		{
			int nx = Now.Now.x + dx[i];
			int ny = Now.Now.y + dy[i];
			if(nx >= 1 && nx <= 5 && ny >= 1 && ny <= 5 &&
				!pVisited[nx][ny] && !pMap[nx][ny])
			{
				State Next = Now;
				Next.Now = Pos(nx, ny);
				Next.Ans.push(Now.Now);
				Q.push(Next);
				pVisited[nx][ny] = true;
			}
		}
	}
	return 0;
}

  

HDU 1241

求连通块个数,直接dfs即可。

#include <iostream>
#include <memory.h>
#include <string>
#include <queue>

using namespace std;

const int MAX = 128;

const int dx[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
const int dy[] = { 1, 1, 1, 0, 0, -1, -1, -1 };

int N, M;
int pMap[MAX][MAX];
bool pVisited[MAX][MAX];

void dfs(int x, int y);

int main()
{
	string strTmp;
	while(cin >> N >> M)
	{
		if(N == 0 && M == 0) { break; }
		for(int i = 1; i <= N; i++)
		{
			cin >> strTmp;
			for(int j = 1; j <= M; j++)
			{
				if(strTmp[j - 1] == ‘*‘) { pMap[i][j] = 1; }
				else { pMap[i][j] = 0; }
			}
		}
		int ans = 0;
		memset(pVisited, false, sizeof(pVisited));
		for(int i = 1; i <= N; i++)
		{
			for(int j = 1; j <= M; j++)
			{
				if(!pMap[i][j] && !pVisited[i][j])
				{
					dfs(i, j);
					ans++;
				}
			}
		}
		cout << ans << endl;
	}
	return 0;
}

void dfs(int x, int y)
{
	pVisited[x][y] = true;
	for(int i = 0; i < 8; i++)
	{
		int nx = x + dx[i];
		int ny = y + dy[i];
		if(nx >= 1 && nx <= N && ny >= 1 && ny <= M &&
			!pMap[nx][ny] && !pVisited[nx][ny])
		{ dfs(nx, ny); }
	}
}

  

HDU 1495

这道题目和POJ 3414非常的类似,但相较来说更简单,也是一道bfs水题。

#include <iostream>
#include <memory.h>
#include <queue>

using namespace std;

const int MAX = 128;

struct Cola
{
	Cola(int _S = 0, int _N = 0, int _M = 0, int _ans = 0)
	{ S = _S; N = _N; M = _M; ans = _ans; }

	int S, N, M, ans;
};

int S, N, M;
bool pVisited[MAX][MAX][MAX];
queue<Cola> Q;

Cola Opt(Cola Now, int k);
bool Check(Cola Now);

int main()
{
	while(cin >> S >> N >> M)
	{
		if(S == 0 && N == 0 && M == 0) { break; }
		if(S & 1) { cout << "NO" << endl; }
		else
		{
			bool bFlag = false;
			memset(pVisited, false, sizeof(pVisited));
			while(!Q.empty()) { Q.pop(); }  // 队列忘记清空
			Q.push(Cola(S, 0, 0, 0)); pVisited[S][0][0] = true;
			while(!Q.empty())
			{
				Cola Now = Q.front(); Q.pop();
				if(Check(Now))
				{
					cout << Now.ans << endl;
					bFlag = true;
					break;
				}
				for(int i = 0; i < 6; i++)
				{
					Cola Next = Opt(Now, i);
					if(!pVisited[Next.S][Next.N][Next.M])
					{
						Q.push(Cola(Next.S, Next.N, Next.M, Next.ans));
						pVisited[Next.S][Next.N][Next.M] = true;
					}
				}
			}
			if(!bFlag) { cout << "NO" << endl; }
		}
	}
	return 0;
}

Cola Opt(Cola Now, int k)
{
	if(k == 0)
	{
		Now.N += Now.S;
		if(Now.N > N) { Now.S = Now.N - N; Now.N = N; }
		else { Now.S = 0; }
	}
	if(k == 1)
	{
		Now.S += Now.N;
		Now.N = 0;
	}
	if(k == 2)
	{
		Now.M += Now.S;
		if(Now.M > M) { Now.S = Now.M - M; Now.M = M; }
		else { Now.S = 0; }
	}
	if(k == 3)
	{
		Now.S += Now.M;
		Now.M = 0;
	}
	if(k == 4)
	{
		Now.N += Now.M;
		if(Now.N > N) { Now.M = Now.N - N; Now.N = N; }
		else { Now.M = 0; }
	}
	if(k == 5)
	{
		Now.M += Now.N;
		if(Now.M > M) { Now.N = Now.M - M; Now.M = M; }
		else { Now.N = 0; }
	}
	Now.ans++;
	return Now;
}

bool Check(Cola Now)
{
	int x = Now.S, y = Now.N, z = Now.M, p = S / 2;
	return (x == p && y == p) || (x == p && z == p) || (y == p && z == p);
}

  

HDU 2612

首先计算Y和M走到地图上每个点的最小时间,然后枚举每个点,计算Y和M走到该点时间和的最小值,最后结果乘以11分钟即可。

#include <iostream>
#include <memory.h>
#include <string>
#include <queue>

using namespace std;

const int MAX = 256;

const int dx[] = { 1, -1, 0, 0 };
const int dy[] = { 0, 0, 1, -1 };

struct Pos
{
	Pos(int _x = 0, int _y = 0, int _s = 0)
	{ x = _x; y = _y; s = _s; }

	int x, y, s;
};

Pos SY, SM;
int N, M;
int pMap[MAX][MAX];
int pAns[2][MAX][MAX];
bool pVisited[MAX][MAX];
queue<Pos> Q;

void Solve(Pos S, int k);

int main()
{
	string strTmp;
	while(cin >> N >> M)
	{
		memset(pAns, -1, sizeof(pAns));
		for(int i = 1; i <= N; i++)
		{
			cin >> strTmp;
			for(int j = 1; j <= M; j++)
			{
				if(strTmp[j - 1] == ‘#‘) { pMap[i][j] = 1; }
				else if(strTmp[j - 1] == ‘@‘) { pMap[i][j] = 2; }
				else { pMap[i][j] = 0; }
				if(strTmp[j - 1] == ‘Y‘) { SY = Pos(i, j, 0); }
				if(strTmp[j - 1] == ‘M‘) { SM = Pos(i, j, 0); }
			}
		}
		Solve(SY, 0); Solve(SM, 1);
		int ans = 2147483647;
		for(int i = 1; i <= N; i++)
		{
			for(int j = 1; j <= M; j++)
			{
				if(pMap[i][j] == 2 && pAns[0][i][j] != -1 && pAns[1][i][j] != -1)
				{ ans = min(ans, pAns[0][i][j] + pAns[1][i][j]); }
			}
		}
		cout << ans * 11 << endl;
	}
	return 0;
}

void Solve(Pos S, int k)
{
	while(!Q.empty()) { Q.pop(); }
	memset(pVisited, false, sizeof(pVisited));
	Q.push(S); pVisited[S.x][S.y] = true;
	while(!Q.empty())
	{
		Pos Now = Q.front(); Q.pop();
		if(pAns[k][Now.x][Now.y] == -1)
		{ pAns[k][Now.x][Now.y] = Now.s; }
		for(int i = 0; i < 4; i++)
		{
			int nx = Now.x + dx[i];
			int ny = Now.y + dy[i];
			if(nx >= 1 && nx <= N && ny >= 1 && ny <= M &&
				!pVisited[nx][ny] && pMap[nx][ny] != 1)
			{
				Q.push(Pos(nx, ny, Now.s + 1));
				pVisited[nx][ny] = true;
			}
		}
	}
}

  

刷完这个专题,感觉对bfs的理解更加深入透彻了。

时间: 2024-10-12 22:52:36

专题一、简单搜索 - Virtual Judge的相关文章

kuangbin带你飞专题一 简单搜索 题解

目录 [kuangbin带你飞]专题一 简单搜索 [kuangbin带你飞]专题一 简单搜索 总结:用时2天半终于把这个专题刷完了 对于最基础的dfs bfs 路径打印 状态转移也有了一点自己些微的理解 其实2天半可以压缩到1天半的 主要是自己太懒了...慢慢加油刷bin神的专题呀 从大二下学期开始学算法 一开始就知道这个专题 一开始对于这个专题里的所有问题感觉都好难啊..就直接放弃了 看lrj的书 现在看到这个专题还挺唏嘘的吧 突然觉得思维和想法也不是很难 果然是那个时候心不静&还是储量不够吗

专题一 简单搜索

本专题主要锻炼搜索的两大方法——bfs (宽度优先搜索)和 dfs (深度优先搜索) ===================================华丽的分割线======================================= 一.bfs——宽度优先搜索 bfs主要运用于搜索中求最短时间的问题,搜索过程中一般需要运用 queue 的操作.具体的操作如下: 1.首先需要将 队列 和 visit数组 清空.(这一点很重要!!!) 2.然后将起点信息 push 进队列,标记为vis

virtual judge(专题一 简单搜索 C)

Description Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer Jo

virtual judge(专题一 简单搜索 B)

Description You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot m

bin巨专题一 简单搜索(更新中

A--棋盘问题 POJ-1321 链接: https://vjudge.net/problem/15202/origin 类似n皇后问题,需要注意的是dfs的边界问题(t在此处 思路:当前走到i/u行j列,判断该点是否可以放棋子,不可以就j++,可以就dfs(i + 1),对放的棋子数进行计数,若等于k则return,记得状态还原. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 us

[kuangbin带你飞]专题一 简单搜索

一直拖.放了放久.受不了 A - 棋盘问题 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Description 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C. Input 输入含有多组测试数据. 每组数据的第

专题一 简单搜索 Problem A

题目链接:http://poj.org/problem?id=1321 题目大意和N皇后类似,只不过可能出现K<N的情况. 按照行的顺序进行深搜,如果当前行可以放置棋子,则换下一行进行搜索. 用一个二维数组描述棋盘,一个一维数组标记此列是否走过. 1 #include<cstdio> 2 #include<cstdlib> 3 4 const int MAXN=8; 5 char m[MAXN][MAXN]; //记录棋盘 6 int vis[MAXN]; //标记每一列是否

[kuangbin带你飞]专题一 简单搜索 bfs B - Dungeon Master

B - Dungeon Master You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You c

[kuangbin带你飞]专题一 简单搜索 - E - Find The Multiple

1 //Memory Time 2 //2236K 32MS 3 4 #include<iostream> 5 using namespace std; 6 7 int mod[524286]; //保存每次mod n的余数 8 //由于198的余数序列是最长的 9 //经过反复二分验证,436905是能存储198余数序列的最少空间 10 //但POJ肯定又越界测试了...524286是AC的最低下限,不然铁定RE 11 12 int main(int i) 13 { 14 int n; 15