萌新求助,这题只能拿300多分...
查看原帖
萌新求助,这题只能拿300多分...
152651
xiyihan楼主2021/1/17 21:07

这两天我没事干,想把这一题给写一下,于是我写了下面的代码:

#include <bits/stdc++.h>
#pragma warning(disable : 4996)
using namespace std;
const double pi = 3.141592653589793;
#define Range(x) (x).begin(), (x).end()
template <typename T>
void chkmax(T& x, T y) { x = max(x, y); }
template <typename T>
void chkmin(T& x, T y) { x = min(x, y); }
const function<int(char)> conv1 = [](const char c) {return c == '.' ? 0 : 1; };
const function<char(int)> conv2 = [](const int c) {return c ? '#' : '.'; };
const char* convtable = "0123456789()+-*/";
//ofstream out("data.out");

struct Image
{
	vector<vector<int>> raw;
	function<int(char)> conv1 = [](const char c) {return int(c); };
	function<char(int)> conv2 = [](const int c) {return char(c); };
	Image() = default;
	int sx, sy;
	Image(int sx, int sy, function<int(char)> c1 = ::conv1, function<char(int)> c2 = ::conv2) :sx(sx), sy(sy), conv1(c1), conv2(c2) {
		raw.resize(sx);
		fill(Range(raw), vector<int>(sy));
	}
	auto& operator[](int x) { return raw[x]; }
	const auto& operator[](int x) const { return raw[x]; }
	//从字符串构造图片
	Image(const string& a, function<int(char)> c1 = ::conv1, function<char(int)> c2 = ::conv2) : conv1(c1), conv2(c2) {
		sx = sy = 0;
		stringstream s1;
		string s2;
		s1 << a;
		while (s1 >> s2) {
			vector<int> s3;
			for (const auto i : s2) {
				s3.push_back(conv1(i));
			}
			raw.push_back(s3);
			sx++;
			chkmax(sy, int(s3.size()));
		}
	}
	Image(const char* a, function<int(char)> c1 = ::conv1, function<char(int)> c2 = ::conv2) : conv1(c1), conv2(c2) {
		sx = sy = 0;
		stringstream s1;
		string s2;
		s1 << a;
		while (s1 >> s2) {
			vector<int> s3;
			for (const auto i : s2) {
				s3.push_back(conv1(i));
			}
			raw.push_back(s3);
			sx++;
			chkmax(sy, int(s3.size()));
		}
	}
	double operator==(const Image& img)
	{
		double cnt = 0;
		for (int i = 0; i < sx; i++)
		{
			for (int j = 0; j < sy; j++)
			{
				cnt += (raw[i][j] == img[i][j]) ? 1 : 0;
			}
		}
		return cnt / double(sx * sy);
	}
	void resize(int nx, int ny){
		sx = nx, sy = ny;
		raw.resize(ny);
		for_each(Range(raw), [=](auto& i) { i.resize(nx); });
	}
	friend ostream& operator<<(ostream& out, const Image& img) {
		for (const auto& i : img.raw) {
			for (const auto j : i)
				cout << img.conv2(j);
			cout << endl;
		}
		return out;
	}
};
#pragma region data
vector<Image> Signset{
R"(
...#########....
..###########...
.#############..
.#####....#####.
#####.....#####.
#####......#####
####.......#####
####.......#####
####.......#####
####.......#####
#####......####.
#####.....#####.
.######..######.
.#############..
...##########...
....#######.....
)",
R"(
....#######.....
.##########.....
###########.....
###########.....
.##..######.....
.....######.....
.....######.....
.....######.....
.....######.....
.....######.....
.....######.....
.....######.....
.....######.....
################
################
################
)",
R"(
.############...
##############..
##############..
#####....######.
#####.....#####.
#####....######.
.........#####..
........######..
......########..
.....#######....
...########.###.
..#######...####
.#######....####
################
################
################
)",
R"(
.############...
.#############..
.##############.
.####.....#####.
.####.....#####.
..........#####.
.....##########.
.....#########..
.....##########.
.........#######
...........#####
..........######
#####....#######
###############.
##############..
..##########....
)",
R"(
........####....
......######....
.....#######....
....########....
...#########....
..##########....
.#####..####....
.#####..####....
################
################
################
........####....
........####....
....###########.
....###########.
....###########.
)",
R"(
.##############.
.##############.
.#############..
.#####..........
.#####..........
.#############..
.##############.
.##############.
.#####...#######
...........#####
...........#####
.#........######
#####....######.
###############.
##############..
..##########....
)",
R"(
......#########.
....###########.
..#############.
.########.......
.######.........
#####...........
##############..
###############.
###############.
#####.....######
####.......#####
#####......#####
#######..######.
.##############.
..############..
....########....
)",
R"(
################
################
###############.
####.....######.
####.....#####..
####....######..
........#####...
.......######...
......######....
......#####.....
.....######.....
.....#####......
....######......
....#####.......
....#####.......
....####........
)",
R"(
...##########...
..############..
.##############.
.#####....#####.
.#####....#####.
.#####....#####.
.##############.
...##########...
.##############.
######...#######
#####......#####
#####.....######
######...#######
###############.
.#############..
...##########...
)",
R"(
..###########...
.#############..
###############.
######....#####.
#####......#####
#####......#####
######...#######
.###############
.###############
...#######.#####
..........#####.
........#######.
.....#########..
.############...
.##########.....
.########.......
)",
R"(
........########
......##########
...##########...
..########......
.#######........
#######.........
#######.........
######..........
######..........
#######.........
########........
.#########......
...########.....
....############
.......#########
.........######.
)",
R"(
#######.........
##########......
..##########....
.....########...
.......#######..
........#######.
.........#######
.........#######
.........#######
.........#######
.......########.
......########..
...##########...
###########.....
########........
######..........
)",
R"(
.....#####......
.....#####......
.....#####......
.....#####......
.....#####......
################
################
################
################
################
.....#####......
.....#####......
.....#####......
.....#####......
.....#####......
......###.......
)",
R"(
###############.
###############.
###############.
################
################
################
################
################
################
################
################
################
################
################
################
################
)",
R"(
......####......
.....#####......
.....#####......
......####......
####..####.#####
#####.##########
################
################
###############.
....########....
....########....
..###########...
.######.######..
.######..#####..
..#####..#####..
...##......#....
)",
R"(
............####
..........######
..........#####.
.........#####..
........######..
.......######...
......#####.....
.....######.....
.....#####......
....#####.......
...######.......
..#####.........
.#####..........
.#####..........
#####...........
####............
)",
};
#pragma endregion This is the sample image data

//对图片进行降噪处理
Image reducenoice(const Image& img)
{
	Image tmp(img);
	auto valid = [&](int x, int y) {return x >= 0 and x < img.sx and y >= 0 and y < img.sy; };
	int dx[] = { 0, 1, 1, 0, -1, -1, -1, 0, 1 };
	int dy[] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 };
	for (int x = 0; x < img.sx; x++) {
		for (int y = 0; y < img.sy; y++) {
			int cnt1 = 0, cnt2 = 0;
			for (int k = 0; k < 9; k++) {
				int nx = x + dx[k], ny = y + dy[k];
				if (valid(nx, ny))
					cnt2++, cnt1 += img[nx][ny];
			}
			tmp[x][y] = (cnt1 * 2 > cnt2);
		}
	}
	return tmp;
}

//将大于minsize大小的联通块分离出来
vector<Image> split(Image img, int minsize = 15)
{
	vector<Image> res;
	queue<pair<int, int>> q;
	int minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN;
	auto init = [&]() {minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN; };
	auto valid = [&](int x, int y) { return x >= 0 and x < img.sx and y >= 0 and y < img.sy; };
	auto bfs = [&](int x, int y) {
		queue<pair<int, int>> q1;
		int dx[] = { 0, 1, 0, -1 }, dy[] = { 1, 0, -1, 0 };
		q1.push({ x, y }); q.push(q1.back());
		chkmax(maxx, x), chkmax(maxy, y), chkmin(minx, x), chkmin(miny, y);
		img[x][y] = 0;
		while (!q1.empty()) {
			auto h = q1.front();
			int x = h.first, y = h.second;
			q1.pop();
			for (int i = 0; i < 4; i++) {
				int nx = x + dx[i], ny = y + dy[i];
				if (valid(nx, ny) and img[nx][ny]) {
					q1.push({ nx, ny }); q.push(q1.back());
					img[nx][ny] = 0;
					chkmax(maxx, nx), chkmax(maxy, ny), chkmin(minx, nx), chkmin(miny, ny);
				}
			}
		}
	};
	for (int j = 0; j < img.sy; j++) {
		for (int i = 0; i < img.sx; i++) {
			if (img[i][j]) {
				init();
				bfs(i, j);
				if (q.size() >= minsize) {
					Image tmpimg(maxx - minx + 1, maxy - miny + 1, img.conv1, img.conv2);
					while (!q.empty()) {
						auto p = q.front(); q.pop();
						int x = p.first, y = p.second;
						tmpimg[x - minx][y - miny] = 1;
					}
					res.push_back(tmpimg);
				}
				while (!q.empty()) q.pop();
			}
		}
	}
	return res;
}

//对图像进行线性拉伸变换
Image resize(const Image& img, int nx, int ny)
{
	Image res(nx, ny);
	/*vector<vector<double>> cnt;
	for (int i = 1; i <= nx; i++)
		cnt.push_back(vector<double>(ny));*/
	auto valid = [=](int x, int y) { return x >= 0 and x < nx and y >= 0 and y < ny; };
	double cx = double(nx) / img.sx, cy = double(ny) / img.sy;
	if (cx < 1)
	{
		for (int i = 0; i < img.sx; i++)
		{
			if (cy < 1)
			{
				for (int j = 0; j < img.sy; j++)
				{
					if (img[i][j])
						res[int(i * cx)][int(j * cy)] = 1;
				}
			}
			else
			{
				for (int j = 0; j < ny; j++)
				{
					if (img[i][int(j / cy)])
						res[int(i * cx)][j] = 1;
				}
			}
		}
	}
	else
	{
		for (int i = 0; i < ny; i++)
		{
			if (cy < 1)
			{
				for (int j = 0; j < img.sy; j++)
				{
					if (img[int(i / cx)][j])
						res[i][int(j * cy)] = 1;
				}
			}
			else
			{
				for (int j = 0; j < ny; j++)
				{
					if (img[int(i / cx)][int(j / cx)])
						res[i][j] = 1;
				}
			}
		}
	}
	return res;
}

//对图像进行旋转变换
Image rotate(const Image& img, double angle)
{
	angle = angle / 180 * pi;
	double minx = 1e5, maxx = -1e5, miny = 1e5, maxy = -1e5;
	vector<pair<double, double>> points;
	auto singlerotate = [](pair<double, double> p, double angle)
	{
		double x = p.second, y = -p.first;
		double nx = x * cos(angle) - y * sin(angle), ny = x * sin(angle) + y * cos(angle);
		return pair<double, double>({ -ny, nx });
	};
	for (int i = 0; i < img.sx; i++)
	{
		for (int j = 0; j < img.sy; j++)
		{
			if (img[i][j])
			{
				points.push_back({ i, j });
				
			}
		}
	}
	for (auto& i : points)
	{
		i = singlerotate(i, angle);
		chkmax(maxx, i.first);
		chkmin(minx, i.first);
		chkmax(maxy, i.second);
		chkmin(miny, i.second);
	}
	Image res(int(maxx - minx + 1), int(maxy - miny + 1));
	for (const auto& i : points)
	{
		int x = (i.first - minx), y = (i.second - miny);
		res[x][y] = 1;
	}
	return res;

}

char recognize(const Image& img)
{
	double rate = 0;
	int idx = -1;
	for (int r = -10; r <= 10; r++)
	{
		Image tmpimg = resize(rotate(img, r), 16, 16);
		//out << tmpimg << endl << endl;
		for (int j = 0; j < 16; j++)
		{
			double r1 = (tmpimg == Signset[j]);
			if (rate < r1)
			{
				rate = r1, idx = j;
			}
		}
	}
	return convtable[idx];
}
int t, n, m;
Image test;
vector<Image> test2, signset;
double calc(const string& s)
{
	vector<double> stk1;
	vector<char> stk2;
	int optnum = 0, isd = 0;
	auto cal = [&](char c)
	{
		int rhs = stk1.back();
		stk1.pop_back();
		int lhs = stk1.back();
		stk1.pop_back();
		switch (c)
		{
		case '+':
			stk1.push_back(lhs + rhs);
			break;
		case '-':
			stk1.push_back(lhs - rhs);
			break;
		case '*':
			stk1.push_back(lhs * rhs);
			break;
		case '/':
			stk1.push_back(lhs / rhs);
			break;
		}
	};
	auto level = [](char c)
	{
		switch (c)
		{
		case '(':
			return 0;
			break;
		case '+':
		case '-':
			return 1;
			break;
		case '*':
		case '/':
			return 2;
			break;
		}
		return -1;
	};
	for (const auto c : s)
	{
		if (c >= '0' and c <= '9')
		{
			optnum = 10 * optnum + (c - 48);
			isd = 1;
		}
		else
		{
			if (isd)
			{
				stk1.push_back(optnum);
				isd = 0;
				optnum = 0;
			}
			
			if (stk2.empty())
			{
				stk2.push_back(c);
			}
			else
			{
				switch (c)
				{
				case '(':
					stk2.push_back(c);
					break;
				case ')':
					while (stk2.back() != '(')
					{
						cal(stk2.back());
						stk2.pop_back();
					}
					stk2.pop_back();
					break;
				default:
					while (!stk2.empty() and level(c) <= level(stk2.back()))
					{
						cal(stk2.back());
						stk2.pop_back();
					}
					stk2.push_back(c);
				}
			}
		}
	}
	if (isdigit(s.back()))
	{
		stk1.push_back(optnum);
	}
	while (!stk2.empty())
	{
		cal(stk2.back());
		stk2.pop_back();
	}
	return stk1.back();
}
int main()
{
	//ifstream in("font.txt");
	//freopen("data.out", "w", stdout);
	/*cout << "vector<Image> signset{\n";
	for (int i = 1; i <= 16; i++)
	{
		string tmp, tmp2;
		for (int j = 1; j <= 65; j++)
		{
			in >> tmp2;
			tmp += tmp2 + '\n';
		}
		auto img = resize(split(Image(tmp))[0], 16, 16);
		signset.push_back(img);
		cout << "R\"(\n" << img << ")\", \n";
	}
	cout << "};";*/
	/*cout << test << endl << endl;
	test1 = reducenoice(test);
	cout << test1 << endl << endl;
	test2 = split(test1);
	for (const auto& i : test2)
	{
		cout << i << endl << endl;
	}
	for (const auto& i : test2)
	{
		cout << resize(i, 16, 16) << endl << endl;
	}
	for (int i = -10; i <= 10; i++)
	{
		cout << reducenoice(rotate(test2[3], i)) << endl << endl;
	}
	test = reducenoice(test);
	test2 = split(test);
	for (const auto& i : test2)
	{
		cout << recognize(i);
	}*/
	//freopen("data.in", "r", stdin);

	string tmp1, tmp2;
	cin >> t >> n >> m;
	while (cin >> tmp2)
	{
		tmp1 += tmp2 + ' ';
	}
	test = Image(tmp1);
	test = reducenoice(test);
	test2 = split(test);
	tmp2.clear();
	for (const auto& i : test2)
	{
		tmp2 += recognize(i);
	}
	//cout << tmp2 << endl << calc(tmp2);

	cout << calc(tmp2) << endl;
}

本来我认为我的程序能够通过此题,但是不幸的是,貌似在后面的数据点中出现了识别错误,如#52:

本来表达式应该是这个样子的:

但我的程序将倒数第三个符号识别为了/,程序结果就出错了......

所以,有谁能帮我指出我识别字符的地方有什么问题吗?......

2021/1/17 21:07
加载中...