谷歌中国算法比赛解题报告 APAC2015A

Problem A. Seven-segment Display

Problem B. Super 2048

Problem C. Addition

Problem D. Cut Tiles


1. 这个题可以用暴力解决,共有七个晶体管,即使计算所有坏掉没坏掉的情况,也就2**7 =128种情况(python写法),而且根据题目,如果输入里某个晶体管是能亮的,就肯定没坏,所以情况数又可以进一步减少,对于每种情况,按9-8-7-6-5-4-3-2-1-0的顺序走一遍,看看输出跟给定输出是否一致就行了,如果一致,储存下一种情况输出。

要注意!!!有可能晶体管坏了,但输出是一样的!最典型的是晶体管都坏了,那么我永远可以预测下个输出是0000000,所以我们要把所有情况便历完,如果下一个输出是固定的(哪怕它是二义的),就可以解题!这是大数据错误率这么高的一大坑!(lz也错在这里了,如果lz参加这场估计也避不开出错)


2. 这个2048 比较简单,生成好矩阵按着顺序滑动就是了,注意新生成的是不能合并的(比如4,2,2向右生成4,4而不是8),所以lz这里把新生成的取了个负号……即保留大小又防止合并……输出的时候用abs输出就好了……


3.  这题难度奇高!小数据其实不难解决,注意 比如要计算a+d, 那么   a+d=(a+x)+(y+d)-(x+y), 所以我们遍历矩阵, 如果 我们能找到一个行x和列y,使得 (a+x)(y+d) (x+y) 都有值,那么就能解出a+d.

要注意还有一种情况 如果我们知道 a+a, d+d 那么我们也能计算a+d

所以做法如下:

先生成计算矩阵,如例子2, a+b=3 b+c=3 c+d=3,我们可以生成

0 3 0 0

3 0 3 0

0 3 0 3

0 0 3 0

先遍历找对角线,然后遍历每一个问题,如果能解决,就更新矩阵,比如这里 a+d=a+b+c+d-(b+c)  计算出a+d 我们把行1列4和行4列1设为3


大数据,用这种思想会超时!

为什么会超时,因为我们搜索了太多没用的行和列。

那么该怎样避免搜索没用的行列呢,倒着推!

依然例子中的求a+d,我们不执著于求a+d,先把矩阵中所有能计算的解都计算了,从a+b开始,a+b是已知的,所以搜索a所在的行,如果这一行除了a 还有值,那么再搜索d所在的列,找到一个 x,y 使得 x+y=a+x+y+b-(a+b) 成立,这样赋值所有x,y。

最后,对于每一个query,如a+c,先查 a+a,c+c是否存在,否则再查a+c是否存在就行了。

这题还有一种用图论的解法,具体思路请上网查……

这题大数据真的很难,倒着推是一个非常有效的减枝,在APAC2017的最后一道题,同样也要用到这样的思想,才能把一个O(n4)复杂度的算法减枝到O(n2)


4.

这个题看起来毫无思路,其实很简单,要注意,题目中的所有的板子都是倍数关系!所以贪心是可行的!

贪心思路如下,先找到最大的板子放到给定的矩形中,然后该矩形就被分成了两个小矩形(随便怎么分都可以,甚至可以分成一个正方形和两个矩形三块)。对每个小矩形重复这个过程,直到放不进为止。

为什么贪心是可行的,给出一个不严谨的证明……因为都是倍数关系,所以如果一个矩形能放进大正方形,那么考虑一个方向,如横向,留下的空隙,跟用小正方形去填原矩形,留下的空隙比,小正方形一定可以通过组合留下相同大小的空隙,而小正方形实用性更高,所以能放大的就放大的……我知道不严谨……具体怎么证明……看你们的了……


最后,附代码,注意对于problemC addition,要把栈的大小设置成0x100000000,因为递归层数非常多……

#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>

using namespace std;

#define ll long long

class PA
{
public:
	PA(){}
	int N;
	int numbers[10];
	vector<string> input;
	vector<int> inputNumber;

	int getIntFromString(string str)
	{
		int ret = 0;
		int val = 64;
		for (int i = 0; i < str.length(); i++)
		{
			if (str[i] == '1') ret += val;
			val = val >> 1;
		}
		return ret;
	}

	string getStringFromInt(int dig)
	{
		int val = 64;
		string ret = "";
		while (val > 0)
		{
			ret += (val&dig) == 0 ? '0':'1';
			val = val >> 1;
		}
		return ret;
	}


	void preDefineNumbers()
	{
		numbers[0] = 126; //1111110
		numbers[1] = 48;  //0110000
		numbers[2] = 109; //1101101
		numbers[3] = 121; //1111001
		numbers[4] = 51;  //0110011
		numbers[5] = 91;  //1011011
		numbers[6] = 95;  //1011111
		numbers[7] = 112; //1110000
		numbers[8] = 127; //1111111
		numbers[9] = 123; //1111011
	}
	int isBroken[7];
	int digits;
	string strDigits;
	string nextNumber = "";
	bool conflict = false;

	void processDigits()
	{
		string temp = "";
		digits = getIntFromString(strDigits);
		
		for (int i = 0; i < 10; i++)
		{
			bool findone = true;
			int curr = i;
			for (int j = 0; j < inputNumber.size(); j++)
			{
				if ((numbers[curr]&digits) != inputNumber[j])
				{
					findone = false;
					break;
				}
				curr--;
				if (curr < 0) curr = 9;
			}

			if (findone)
			{
				//Be careful!!!
				string temp = getStringFromInt(numbers[curr] & digits);
				if (nextNumber == "")
				{
					nextNumber = temp;
				}
				else
				{
					if (nextNumber != temp)
					{
						conflict = true;
						return;
					}
				}
				
			}
		}
	}


	void DFS(int depth)
	{
		if (conflict) return;
		if (depth == 7)
		{
			processDigits();
			return;
		}
		if (isBroken[depth])
		{
			strDigits.push_back('0');
			DFS(depth + 1);
			strDigits.pop_back();
		}
		strDigits.push_back('1');
		DFS(depth + 1);
		strDigits.pop_back();
	}

	string SingleProcess()
	{
		memset(isBroken, true, sizeof(isBroken));
		inputNumber.clear();
		for (int i = 0; i < input.size(); i++)
		{
			for (int j = 0; j < 7; j++)
			{
				if (input[i][j] == '1') isBroken[j] = false;
			}
			inputNumber.push_back(getIntFromString(input[i]));
		}
		strDigits = "";
		conflict = false;
		nextNumber = "";
		strDigits = "";

		DFS(0);

		if (conflict || nextNumber == "")
		{
			return "ERROR!";
		}
		else
		{
			return nextNumber;
		}
	}

	void run()
	{
		FILE* fp = freopen("in.txt", "r", stdin);
		ofstream fout("out.txt");
		int Cases = 0;
		scanf("%d", &Cases);
		preDefineNumbers();
		for (int time = 0; time < Cases; time++)
		{
			scanf("%d", &N);
			input.resize(N, "");
			char ch[10];
			for (int i = 0; i < N; i++)
			{
				scanf("%s", ch);
				input[i] = ch;
			}

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


class PB
{
public:
	PB(){}
	int N;
	vector<vector<int>> board;
	string direction;

	void moveDir(int dirRow,int dirCol)
	{
		if (dirCol != 0)
		{
			for (int col = 0; col < N; col++)
			{

				for (int row = dirCol==1?0:N-1; row < N&&row>=0; row+=dirCol)
				{
					if (board[row][col] != 0)
					{
						int k = row - dirCol;
						while (k>=0&&k < N&&board[k][col] == 0)
						{
							k-=dirCol;
						}
						if (k == N)
						{
							swap(board[N - 1][col], board[row][col]);
						}
						else if (k < 0)
						{
							swap(board[0][col] , board[row][col]);
						}
						else
						{
							if (board[k][col] == board[row][col]){
								board[k][col] *= -2;   //做一个小处理,负数保证不会跟后面数字合成,同时保留了大小。。。
								board[row][col] = 0;
							}
							else
							{
								swap(board[k + dirCol][col] , board[row][col]);
							}
						}
					}
				}
			}
		}
		else
		{
			for (int row = 0; row < N; row++)
			{
				for (int col = dirRow==1?N-2:0; col < N&&col>=0; col-=dirRow)
				{
					if (board[row][col] != 0)
					{
						int k = col + dirRow;
						while (k >= 0 && k < N&&board[row][k] == 0)
						{
							k += dirRow;
						}
						if (k == N)
						{
							swap(board[row][N-1] , board[row][col]);
						}
						else if (k < 0)
						{
							swap(board[row][0], board[row][col]);
						}
						else
						{
							if (board[row][k] == board[row][col]){
								board[row][k] *= -2;   //做一个小处理,负数保证不会跟后面数字合成,同时保留了大小。。。
								board[row][col] = 0;
							}
							else
							{
								swap(board[row][k - dirRow], board[row][col]);
							}
						}
					}
				}
			}
		}
	}






	int SingleProcess(ofstream& fout)
	{
		if (direction == "up")
		{
			moveDir(0, 1);
		}
		else if (direction == "down")
		{
			moveDir(0, -1);
		}
		else if (direction == "left")
		{
			moveDir(-1, 0);
		}
		else if (direction == "right")
		{
			moveDir(1, 0);
		}

		for (int i = 0; i < board.size(); i++)
		{
			for (int j = 0; j < board.size(); j++)
			{
				fout << abs(board[i][j]) << " ";
			}
			fout << endl;
		}
		return 0;
	}

	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++)
		{
			scanf("%d", &N);
			char ch[20];
			scanf("%s", ch);
			direction = ch;
			board.clear();
			board.resize(N, vector<int>(N, 0));
			for (int i = 0; i < N; i++)
			{
				for (int j = 0; j < N; j++)
				{
					scanf("%d", &board[i][j]);
				}
			}
			fout << "Case #" << (time + 1) << ": \n";
			SingleProcess(fout);
			std::cout << time << endl;
		}
		fclose(fp);
		fout.close();
	}
};



//why so slow???
class PC
{
public:
	PC(){}
	int N,Q;
	int K;
	struct QLine{
		string x;
		string y;
		int z;
		QLine(){ x = y = ""; z = 0; }
	};
	vector<QLine> questions;
	vector<QLine> equations;
	unordered_map<string, int> hmap;
	vector<vector<int>> matrix;
	vector<set<int>> fset;

	void matrixPorcess(ofstream& fout)
	{
		K = hmap.size();
		matrix.clear();
		matrix.resize(K, vector<int>(K, INT_MAX));
		fset.clear();
		fset.resize(K, set<int>());
		for (int i = 0; i < equations.size(); i++)
		{
			int r = hmap[equations[i].x];
			int c = hmap[equations[i].y];
			matrix[r][c] = equations[i].z;
			matrix[c][r] = equations[i].z;
			fset[r].insert(c);
			fset[c].insert(r);
		}

		set<int>::iterator iter, iter2;
		while (true)
		{
			bool findone = false;
			for (int i = 0; i < K; i++)
			{
				for (int j = 0; j < K; j++)
				{
					if (matrix[i][j] == INT_MAX)
					{
						if (matrix[i][i] != INT_MAX&&matrix[j][j] != INT_MAX)
						{
							matrix[i][j] = (matrix[i][i] + matrix[j][j]) / 2;
							matrix[j][i] = matrix[i][j];
							findone = true;
						}
						else
						{
							for (iter = fset[i].begin(); iter != fset[i].end(); iter++)
							{
								for (iter2 = fset[j].begin(); iter2 != fset[j].end(); iter2++)
								{
									if (matrix[*iter][*iter2] == INT_MAX) continue;
									matrix[i][j] = matrix[i][*iter] + matrix[j][*iter2] - matrix[*iter][*iter2];
									matrix[j][i] = matrix[i][j];
									fset[i].insert(j);
									fset[j].insert(i);
									findone = true;
									break;
								}
								if (matrix[i][j] != INT_MAX) break;
							}
						}

					}
				}
			}
			if (!findone) break;
		}

		string ret = "";
		for (int i = 0; i < questions.size(); i++)
		{
			if (hmap.find(questions[i].x) == hmap.end() || hmap.find(questions[i].y) == hmap.end()) continue;
			int r = hmap[questions[i].x];
			int c = hmap[questions[i].y];
			if (matrix[r][c] != INT_MAX)
			{
				fout << "\n" << questions[i].x.c_str() << "+" << questions[i].y.c_str() << "=" << matrix[r][c];
			}
		}
	}


	vector<vector<bool>> visited;

	void reverseDFSInit(int row, int col,int depth)
	{
		if (matrix[row][col] == INT_MAX) return;
		if(depth>0&& depth%1000==0) cout << depth << endl;

		for (set<int>::iterator it1 = fset[row].begin(); it1 != fset[row].end(); it1++)
		{
			for (set<int>::iterator it2 = fset[col].begin(); it2 != fset[col].end(); it2++)
			{
				if (matrix[*it1][*it2] == INT_MAX)
				{
					int val = matrix[*it1][row] + matrix[*it2][col] - matrix[row][col];
					matrix[*it1][*it2] = val;
					matrix[*it2][*it1] = val;
					reverseDFSInit(*it1, *it2,depth+1);
				}
			}
		}
	}


	int DFSfindValue(int row, int col,int depth)
	{
		if (matrix[row][col] != INT_MAX) return matrix[row][col];
		
		if (visited[row][col]) return INT_MAX;
		visited[row][col] = true;
		visited[col][row] = true;
		if(depth>0&&depth%1000==0) cout << depth << endl;
		

		//row x y col x,y
		for (set<int>::iterator it1 = fset[row].begin(); it1 != fset[row].end(); it1++)
		{
			for (set<int>::iterator it2 = fset[col].begin(); it2 != fset[col].end(); it2++)
			{
				if (matrix[*it1][*it2] != INT_MAX)
				{
					int val = matrix[*it1][row] + matrix[*it2][col] - matrix[*it1][*it2];
					matrix[row][col] = val;
					matrix[col][row] = val;
					return val;
				}
				
			}
		}

		for (set<int>::iterator it1 = fset[row].begin(); it1 != fset[row].end(); it1++)
		{
			for (set<int>::iterator it2 = fset[col].begin(); it2 != fset[col].end(); it2++)
			{
				int val = DFSfindValue(*it1, *it2, depth + 1);
				if (val != INT_MAX)
				{
					val = matrix[*it1][row] + matrix[*it2][col] - val;
					matrix[row][col] = val;
					matrix[col][row] = val;
					return val;
				}
			}
		}

		
		return INT_MAX;
	}

	void matrixDFS(ofstream& fout)
	{
		K = hmap.size();
		matrix.clear();
		matrix.resize(K, vector<int>(K, INT_MAX));

		fset.clear();
		fset.resize(K, set<int>());
		for (int i = 0; i < equations.size(); i++)
		{
			int r = hmap[equations[i].x];
			int c = hmap[equations[i].y];
			matrix[r][c] = equations[i].z;
			matrix[c][r] = equations[i].z;
			fset[r].insert(c);
			fset[c].insert(r);
		}

		for (int i = 0; i < fset.size(); i++)
		{
			for (set<int>::iterator iter = fset[i].begin(); iter != fset[i].end(); iter++)
			{
				reverseDFSInit(i, *iter,0);
			}
		}

		//先计算对角线
		//visited.clear();
		//visited.resize(K, vector<bool>(K, false));
		//for (int i = 0; i < K; i++)
		//{
		//	if (i == 1666)
		//	{
		//		i++;
		//		i--;
		//	}
		//	int val = DFSfindValue(i, i,0);
		//	if (val != INT_MAX)
		//	{
		//		matrix[i][i] = val;
		//	}
		//	//cout << i << endl;
		//}

		//再计算每一个question
		for (int i = 0; i < questions.size(); i++)
		{
			if (hmap.find(questions[i].x) == hmap.end() || hmap.find(questions[i].y) == hmap.end()) continue;
			int r = hmap[questions[i].x];
			int c = hmap[questions[i].y];
			if (matrix[r][r] != INT_MAX&&matrix[c][c] != INT_MAX)
			{
				fout << "\n" << questions[i].x.c_str() << "+" << questions[i].y.c_str() << "=" << (matrix[r][r]+matrix[c][c])/2;
			}
			else if (matrix[r][c]!=INT_MAX)
			{
				fout << "\n" << questions[i].x.c_str() << "+" << questions[i].y.c_str() << "=" << matrix[r][c];
				/*cout << i << endl;
				int val = DFSfindValue(r, c,0);
				if(val!=INT_MAX) fout << "\n" << questions[i].x.c_str() << "+" << questions[i].y.c_str() << "=" << val;*/
			}
		}
	}




	struct Node
	{
		int val;
		vector<Node*> neighbor;
		Node(){ val = 0; }
	};

	void SingleProcess(ofstream& fout)
	{
		matrixDFS(fout);
	}

	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++)
		{
			scanf("%d",&N);
			hmap.clear();
			questions.clear();
			equations.clear();
			matrix.clear();
			string line;
			string ch1, ch2;
			char ln[64];
			int ans;
			int c = 0;
			equations.resize(N, QLine());
			for (int i = 0; i < N; i++)
			{
				scanf("%s", ln);
				line = ln;
				int t1 = line.find_first_of('+');
				ch1 = line.substr(0, t1);
				line = line.substr(t1 + 1);
				t1 = line.find_first_of('=');
				ch2 = line.substr(0, t1);
				line = line.substr(t1 + 1);
				ans = atoi(line.c_str());
				if (hmap.find(ch1) == hmap.end())
				{
					hmap[ch1] = c++;
				}
				if (hmap.find(ch2) == hmap.end())
				{
					hmap[ch2] = c++;
				}
				equations[i].x = ch1;
				equations[i].y = ch2;
				equations[i].z = ans;
			}
			scanf("%d", &Q);
			questions.resize(Q, QLine());
			for (int i = 0; i < Q; i++)
			{
				scanf("%s", ln);
				line = ln;
				int t1 = line.find_first_of('+');
				ch1 = line.substr(0, t1);
				ch2 = line.substr(t1 + 1);
				questions[i].x = ch1;
				questions[i].y = ch2;
			}

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


class PD
{
public:
	PD(){}
	int M, N;
	map<int,int> tiles;

	//根据题目的数据,不可能留下空隙,因为都是倍数关系
	int DFSPut(int width, int height)
	{
		//iter-- 需要保证map非空
		if (tiles.empty()) return 0;

		if (width <= height)
		{
			map<int, int>::iterator iter = tiles.lower_bound(width);
			if (iter != tiles.end() && iter->first == width)
			{

			}
			else
			{
				iter--;
			}
			if (iter != tiles.end())
			{
				int l = iter->first;
				iter->second--;
				if (iter->second == 0) tiles.erase(iter);
				return 1 + DFSPut(width - l, l) + DFSPut(width, height - l);
			}
			else
			{
				return 0;
			}
		}
		else
		{
			map<int, int>::iterator iter = tiles.lower_bound(height);
			if (iter != tiles.end() && iter->first == height)
			{

			}
			else
			{
				iter--;
			}
			if (iter != tiles.end())
			{
				int l = iter->first;
				iter->second--;
				if (iter->second == 0) tiles.erase(iter);
				return 1 + DFSPut(l, height - l) + DFSPut(width-l, height);
			}
			else
			{
				return 0;
			}
		}
	}

	int SingleProcess()
	{
		int count = 0;
		int puted = 0;
		map<int, int>::iterator iter;
		while (puted < N)
		{
			puted += DFSPut(M, M);
			count++;
		}
		return count;
	}

	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;
			tiles.clear();
			for (int i = 0; i < N; i++)
			{
				int temp;
				cin >> temp;
				temp = pow(2, temp);
				tiles[temp]++;
			}


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




int main()
{
	//PA p;
	//PB p;
	PC p;
	//PD p;
	p.run();

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值