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;
}