谷歌中国算法比赛结题报告 APAC2014B

Problem A. Sudoku Checker

Problem B. Meet and party

Problem C. Hex

Problem D. Dragon Maze

Problem E. Ignore all my comments


1.这道题依旧送分,以9*9矩阵为例,先准备一个1-9的bool数组初始化为false,然后按第一行扫一遍,没找到一个数字就把bool数组对应位置设true,扫完后看看bool数组是否全true,是的话重新初始化bool数组继续扫第二行,第三行。。。,扫完行扫列,然后扫3*3矩阵块


2.这道题大数据有一定难度,基本思路如下:

首先因为必须在参与的人家里举行,所以暴力解法可以对每一个矩阵块的每一个位置进行计算,求出和最短的距离

然后思考,对每一个矩阵块,先计算左上角节点,注意计算该节点所有左边的节点的横向和和右边节点的横向和,然后该节点向右横向移动,注意没向右横向移动一格,所有左边的节点横向距离都会加1,右边的节点横向距离都会减1,要注意该节点压到的那一列和之前压到的那一列要特殊处理。 当节点找到横向最小的节点后,同理向下移动。可以找到该矩阵的最优的节点,对每个矩阵都进行一次这样的操作,就可以解题了


3.这道题要先分清楚各种情况

(1)因为是轮流下子,所以如果一方子比另一方多二,则impossible

(2)因为获胜立刻结束,所以如果获胜一方有两条通路,则impossible

         如何判断有两条通路,先dfs找到任一条通路,然后删除通路上一个点,再一次通路,如果找到,先把删除的点还原,然后对新的通路跟上一条通路取交,这些相交的点中,重复去掉一个点,找通路,求交,如果存在一个点,删除掉后没有通路,则这个点是最后下的,否则就是impossible.

(3)如果双方都获胜,impossible

(4)如果获胜方棋子比失败方少,impossible。这点很好理解,但不太容易发现……

(5)如果只有一方胜利,则胜出

(6)没有人胜利,则nobody wins.


4. 这题解法应该挺多,我用的是bfs,一层一层的向外扩散,如果某一层找到出口,就计算完这一层(毕竟要计算能得到的最大能量),然后退出,返回获得的最大能量。


5. 这题和经典的左括号 右括号匹配很像,读取文件后,记录有多少个没匹配的/*, 如果找到/* 就记录加1,找到 */ 就记录减1,记录不为0则忽略字符。 因为按题目给的数据,不会有 /* 比 */ 多的情况…… 所以很容易就过了(我练习时本来想跑一下看看哪里没注意到,结果就过了……)


最后 附代码:

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <hash_map>
#include <hash_set>
#include <unordered_map>
#include <unordered_set>
#include <string.h>
#include <queue>
#include <list>
#include <iomanip>
#include <iterator>

using namespace std;

#define ll long long
#define uint unsigned int


class PA
{
public:
	PA(){}
	int N, NN;
	vector<vector<int>> board;


	void SingleProcess(ofstream& fout)
	{
		bool visited[1024];
		memset(visited, 0, sizeof(visited));

		//检测每一行
		for (int row = 0; row < NN; row++)
		{
			memset(visited, 0, sizeof(visited));
			for (int col = 0; col < NN; col++)
			{
				visited[board[row][col]] = true;
			}
			for (int i = 1; i <= NN; i++)
			{
				if (visited[i] == false)
				{
					fout << "No";
					return;
				}
			}
		}

		//检测每一列
		for (int col = 0; col < NN; col++)
		{
			memset(visited, 0, sizeof(visited));
			for (int row = 0; row < NN; row++)
			{
				visited[board[row][col]] = true;
			}
			for (int i = 1; i <= NN; i++)
			{
				if (visited[i] == false)
				{
					fout << "No";
					return;
				}
			}
		}

		//检测每一个方格
		for (int colStart = 0; colStart < NN; colStart += N)
		{
			for (int rowStart = 0; rowStart < NN; rowStart += N)
			{
				memset(visited, 0, sizeof(visited));
				for (int row = 0; row < N; row++)
				{
					for (int col = 0; col < N; col++)
					{
						visited[board[rowStart + row][colStart + col]] = true;
					}
				}


				for (int i = 1; i <= NN; i++)
				{
					if (visited[i] == false)
					{
						fout << "No";
						return;
					}
				}

			}
		}

		fout << "Yes";
	}

	void run()
	{
		FILE* fp = freopen("in.txt", "r", stdin);
		ofstream fout("out.txt");
		int Cases = 0;
		scanf("%d", &Cases);
		for (int time = 0; time < Cases; time++)
		{
			cin >> N;
			NN = N*N;
			board.clear();
			board.resize(NN, vector<int>(NN, 0));
			for (int i = 0; i < NN; i++)
			{
				for (int j = 0; j < NN; j++)
				{
					cin >> board[i][j];
				}
			}


			fout << "Case #" << (time + 1) << ": ";
			SingleProcess(fout);
			fout << endl;
			std::cout << time << endl;
		}
		fclose(fp);
		fout.close();
	}
};

class PB
{
public:
	PB(){}
	int B;
	struct Rectangle
	{
		ll x1, x2, y1, y2;
		Rectangle(){ x1 = x2 = y1 = y2 = 0; }
		int getWidth()
		{
			return x2-x1+1;
		}
		int getHeight()
		{
			return y2 - y1+1;
		}
	};
	vector<Rectangle> recs;

	void SingleProcess(ofstream& fout)
	{
		ll left, right, up, down;
		ll cleft, cright, cup, cdown;
		map<ll, ll> lineCount;
		map<ll, ll> columnCount;

		for (int i = 0; i < recs.size(); i++)
		{
			for (int j = recs[i].x1; j <= recs[i].x2; j++)
			{
				lineCount[j] += recs[i].getHeight();
			}
		}

		for (int i = 0; i < recs.size(); i++)
		{
			for (int j = recs[i].y1; j <= recs[i].y2; j++)
			{
				columnCount[j] += recs[i].getWidth();
			}
		}


		ll minD, minX, minY;
		minD = minX = minY = 0x7fffffffffffffff;

		for (int i = 0; i < recs.size(); i++)
		{
			ll currX, currY;
			currX = recs[i].x1;
			currY = recs[i].y1;
			map<ll, ll>::iterator iter, iter2;
			cleft = cright = left = right = cup = cdown = up = down = 0;
			for (iter = lineCount.begin(); iter != lineCount.end(); iter++)
			{
				if (iter->first < currX)
				{
					cleft += iter->second;
					left += iter->second*(currX-iter->first);
				}
				else if (iter->first>currX)
				{
					cright += iter->second;
					right += iter->second*(iter->first - currX);
				}
			}

			ll totalX = left + right;
			ll tx = currX + 1;
			while (tx<=recs[i].x2)
			{
				iter = lineCount.find(tx);
				cleft += iter->second;
				left += cleft;

				right -= cright;
				cright -= iter->second;

				if (totalX > left + right)
				{
					currX = tx;
					tx++;
					totalX = left + right;
				}
				else break;
			}



			for (iter = columnCount.begin(); iter != columnCount.end(); iter++)
			{
				if (iter->first < currY)
				{
					cup += iter->second;
					up += iter->second*(currY - iter->first);
				}
				else if (iter->first>currY)
				{
					cdown += iter->second;
					down += iter->second*(iter->first - currY);
				}
			}
			ll totalY = up + down;
			ll ty = currY + 1;
			while (ty <= recs[i].y2)
			{
				iter = columnCount.find(ty);
				cup += iter->second;
				up += cup;

				down -= cdown;
				cdown -= iter->second;
				if (totalY > up + down)
				{
					currY = ty;
					ty++;
					totalY = up + down;
				}
				else break;
			}

			if (minD > totalX + totalY)
			{
				minX = currX;
				minY = currY;
				minD = totalX + totalY;
			}
			else if (minD == totalX + totalY)
			{
				if ((minX > currX) || (minX == currX&&minY > currY))
				{
					minX = currX;
					minY = currY;
				}
			}
		}

		fout << minX << " " << minY << " " << minD;
	}

	void run()
	{
		FILE* fp = freopen("in.txt", "r", stdin);
		ofstream fout("out.txt");
		int Cases = 0;
		scanf("%d", &Cases);
		for (int time = 0; time < Cases; time++)
		{
			cin >> B;
			recs.resize(B, Rectangle());
			for (int i = 0; i < B; i++)
			{
				cin >> recs[i].x1 >> recs[i].y1 >> recs[i].x2 >> recs[i].y2;
			}

			fout << "Case #" << (time + 1) << ": ";
			SingleProcess(fout);
			fout << endl;
			std::cout << time << endl;
		}
		fclose(fp);
		fout.close();
	}
};

class PC
{
public:
	PC(){}
	int N;
	vector<vector<char>> board;
	bool visited[101][101];
	set<pair<int, int>> path1, path2;
	bool findone;


	void DFS(int row, int col, char target)
	{
		if (findone) return;

		if (board[row][col] == target)
		{
			visited[row][col] = true;
			path1.insert(make_pair(row, col));

			if (target=='B'&&col == N - 1)
			{
				findone = true;
				return;
			}
			else if (target == 'R'&&row == N - 1)
			{
				findone = true;
				return;
			}
			
			if (row > 0)
			{
				if(!visited[row-1][col]) DFS(row - 1, col, target);
				if (col < N - 1 && !visited[row - 1][col+1]) DFS(row - 1, col + 1, target);
			}
			if (col>0)
			{
				if (!visited[row][col-1]) DFS(row, col - 1, target);
			}
			if (col < N - 1&&!visited[row][col+1]) DFS(row, col + 1, target);
			if (row < N - 1&&!visited[row + 1][col-1])
			{
				DFS(row + 1, col, target);
				if (col>0&&!visited[row +1][col-1]) DFS(row + 1, col - 1, target);
			}
			if (findone) return;
			//visited[row][col] = false;
			path1.erase(make_pair(row, col));
		}
	}

	int checkWin(char target)
	{
		for (int i = 0; i < N; i++)
		{
			path1.clear();
			memset(visited, false, sizeof(visited));
			findone = false;
			if (target == 'B')
			{
				DFS(i, 0, target);
				if (findone) break;
			}
			else if (target == 'R')
			{
				DFS(0, i, target);
				if (findone) break;
			}
		}
		if (!findone) return 0;

		//断掉路径上的一个点, 查看是否还能连通
		path2 = path1;
		for (set<pair<int, int>>::iterator iter = path2.begin(); iter != path2.end();)
		{
			pair<int, int> pi = *iter;
			board[pi.first][pi.second] = '.';

			for (int i = 0; i < N; i++)
			{
				path1.clear();
				memset(visited, false, sizeof(visited));
				findone = false;
				if (target == 'B')
				{
					DFS(i, 0, target);
				}
				else if (target == 'R')
				{
					DFS(0, i, target);
				}
				if (findone)
				{
					//找到一条路径,需要检测的点取两条路径相交的部分
					set<pair<int, int>> newSet;
					set_intersection(path1.begin(), path1.end(), path2.begin(), path2.end(), inserter(newSet,newSet.begin()));
					/*for (iter = path1.begin(); iter != path1.end(); iter++)
					{
						if (path2.find(*iter) != path2.end())
						{
							newSet.insert(*iter);
						}
					}*/
					path2 = newSet;
					iter = path2.begin();
					break;
				}
			}
			board[pi.first][pi.second] = target;
			if (!findone) return 1; //去掉某个点后找不到路径,说明这个点是最后一个放的
		}
		return -1;//去掉任何一个点都能找到路径,说明有多个不相交路径,不符合游戏立即结束
	}


	void SingleProcess(ofstream& fout)
	{
		int Rcount, Bcount;
		Rcount = Bcount = 0;
		for (int i = 0; i < board.size(); i++)
		{
			for (int j = 0; j < N; j++)
			{
				if (board[i][j] == 'R') Rcount++;
				else if (board[i][j] == 'B') Bcount++;
			}
		}
		if (abs(Rcount - Bcount)>1)
		{
			fout << "Impossible";
			return;
		}

		int blueWin = checkWin('B');
		int redWin = checkWin('R');

		if (blueWin<0 || redWin<0) fout << "Impossible";
		else if (blueWin&&redWin) fout << "Impossible";
		else if (blueWin&&Bcount<Rcount) fout << "Impossible";
		else if (redWin&&Rcount < Bcount) fout << "Impossible";
		else if (blueWin) fout << "Blue wins";
		else if (redWin) fout << "Red wins";
		else fout << "Nobody wins";
	}

	void run()
	{
		FILE* fp = freopen("in.txt", "r", stdin);
		ofstream fout("out.txt");
		int Cases = 0;
		scanf("%d", &Cases);
		for (int time = 0; time < Cases; time++)
		{
			cin >> N;
			board.clear();
			board.resize(N, vector<char>(N, 0));
			for (int i = 0; i < N; i++)
			{
				for (int j = 0; j < N; j++)
				{
					cin >> board[i][j];
				}
			}


			fout << "Case #" << (time + 1) << ": ";
			SingleProcess(fout);
			fout << endl;
			std::cout << time << endl;
		}
		fclose(fp);
		fout.close();
	}
};

class PD
{
public:
	PD(){}
	int M, N;
	int SX, SY, EX, EY;

	vector<vector<int>> maze;

	void SingleProcess(ofstream& fout)
	{
		int visited[101][101];
		memset(visited, 0xff, sizeof(visited));

		set<pair<int, int>> posVec1, posVec2, *currSet, *nextSet;
		posVec1.insert(make_pair(SX, SY));
		visited[SX][SY] = maze[SX][SY];
		maze[SX][SY] = -1;
		currSet = &posVec1;
		nextSet = &posVec2;

		while (!currSet->empty())
		{
			nextSet->clear();

			for (set<pair<int,int>>::iterator iter=currSet->begin(); iter!=currSet->end(); iter++)
			{
				int row, col;
				row = iter->first - 1;
				col = iter->second;
				if (row>=0 && maze[row][col] != -1)
				{
					visited[row][col] = max(visited[row][col], visited[iter->first][iter->second] + maze[row][col]);
					nextSet->insert(make_pair(row, col));
				}

				row = iter->first + 1;
				col = iter->second;
				if (row <N && maze[row][col] != -1)
				{
					visited[row][col] = max(visited[row][col], visited[iter->first][iter->second] + maze[row][col]);
					nextSet->insert(make_pair(row, col));
				}

				row = iter->first;
				col = iter->second-1;
				if (col>=0 && maze[row][col] != -1)
				{
					visited[row][col] = max(visited[row][col], visited[iter->first][iter->second] + maze[row][col]);
					nextSet->insert(make_pair(row, col));
				}

				row = iter->first;
				col = iter->second+1;
				if (col <M && maze[row][col] != -1)
				{
					visited[row][col] = max(visited[row][col], visited[iter->first][iter->second] + maze[row][col]);
					nextSet->insert(make_pair(row, col));
				}
			}

			for (set<pair<int, int>>::iterator iter = nextSet->begin(); iter != nextSet->end(); iter++)
			{
				maze[iter->first][iter->second] = -1;
			}
			swap(currSet, nextSet);
		}

		if (visited[EX][EY] < 0) fout << "Mission Impossible.";
		else fout << visited[EX][EY];
	}

	void run()
	{
		FILE* fp = freopen("in.txt", "r", stdin);
		ofstream fout("out.txt");
		int Cases = 0;
		scanf("%d", &Cases);
		for (int time = 0; time < Cases; time++)
		{
			cin >> N >> M;
			cin >> SX >> SY >> EX >> EY;
			maze.clear();
			maze.resize(N, vector<int>(M, 0));
			for (int i = 0; i < N; i++)
			{
				for (int j = 0; j < M; j++)
				{
					cin >> maze[i][j];
				}
			}

			fout << "Case #" << (time + 1) << ": ";
			SingleProcess(fout);
			fout << endl;
			std::cout << time << endl;
		}
		fclose(fp);
		fout.close();
	}
};

class PE
{
public:
	PE(){}
	int M, N;
	string paragraph;
	int left;

	void SingleProcess(ofstream& fout)
	{
		string ret = "";
		left = 0;
		for (int i = 0; i < paragraph.length(); i++)
		{
			if (paragraph[i] == '/' && i + 1 < paragraph.length() && paragraph[i + 1] == '*')
			{
				left++;
				i++;
			}
			else if (left > 0 && paragraph[i] == '*'&&i + 1 < paragraph.length() && paragraph[i + 1] == '/')
			{
				left--;
				i++;
			}
			else if (left == 0)
			{
				ret += paragraph[i];
			}
			else
			{
				continue;
			}
		}
		fout << ret.c_str();
	}

	void run()
	{
		FILE* fp = freopen("in.txt", "r", stdin);
		ofstream fout("out.txt");
		//int Cases = 0;
		//scanf("%d", &Cases);
		//for (int time = 0; time < Cases; time++)
		{
			char ch;
			paragraph.clear();
			while (true)
			{
				cin.get(ch);
				if (cin.eof()) break;
				paragraph.push_back(ch);
			}

			fout << "Case #1:\n";
			SingleProcess(fout);
			//fout << endl;
			std::cout << time << endl;
		}
		fclose(fp);
		fout.close();
	}
};



int main()
{
	//PA p;
	//PB p;
	//PC p;
	//PD p;
	//PE p;
	//p.run();
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值