这两天我没事干,想把这一题给写一下,于是我写了下面的代码:
#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:
本来表达式应该是这个样子的:
但我的程序将倒数第三个符号识别为了/
,程序结果就出错了......
所以,有谁能帮我指出我识别字符的地方有什么问题吗?......