作业
第一题 Maze
题意
在一个5* 5的迷宫中从(0,0)走到(4,4),迷宫直接通过5*5的二维数组给出,0为可走,1为不可走。找到最短路径。
思路
可以使用BFS算法来求解,同时声明2个二维数组lx,ly,已记录每个节点被遍历过来前驱点x,y坐标。BFS起始节点为(0,0),当遍历到目标节点后,迭代lx,ly找到最短的路径,倒序输出完成。
代码
#include <iostream>
#include <queue>
using namespace std;
int x[4] = {1, -1, 0, 0};
int y[4] = {0, 0, 1, -1};
struct point
{
int x0;
int y0;
point(int xo, int yo)
{
x0 = xo;
y0 = yo;
}
};
int main()
{
int l[5][5];
int lx[5][5];
int ly[5][5];
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
cin >> l[i][j];
lx[i][j] = 0;
ly[i][j] = 0;
}
}
queue<point> q;
int a = 0;
int b = 0;
l[0][0] = 1;
point p(a, b);
q.push(p);
while (!q.empty())
{
point p2 = q.front();
q.pop();
int nx = p2.x0;
int ny = p2.y0;
for (int i = 0; i < 4; i++)
{
int a = nx + x[i];
int b = ny + y[i];
if (0 <= a && a <= 4 && b >= 0 && b <= 4)
{
if (l[a][b] != 1)
{
l[a][b] = 1;
p.x0 = a;
p.y0 = b;
q.push(p);
lx[a][b] = nx;
ly[a][b] = ny;
}
}
}
}
int num = 1;
int m[1000];
int n[1000];
int w, e;
w = 4;
e = 4;
m[0] = w;
n[0] = e;
while (!(w == 0 && e == 0))
{
int w2 = lx[w][e];
int e2 = ly[w][e];
w = w2;
e = e2;
m[num] = w;
n[num] = e;
num++;
}
for (int i = num - 1; i >= 0; i--)
{
cout << "(" << m[i] << ", " << n[i] << ")" << endl;
}
}
第二题
题意
有A、B两个杯子,每个杯子可以进行装满、倒空、倒入另一个杯这三种操作,最后使杯中含有C单位的水。输入直接为A、B、C三个数字,表示A、B两个杯子和要求的C单位水。其中A<=B,C<=B。
思路
若要求最少操作步骤,则要使用隐式图的BFS,但由于题目没有要求最少的操作步骤,可以使用简单的方法。
由于A,B互质,所以对于任意C,存在x,使得(x*B)%A=C。所以可以模拟这个过程。将B倒满水后,向A中倒水,如果A中水满了,则将A杯倒空;如果B空,则倒满B。当B中水等于C时,结束。
#include <stdio.h>
void doo(int va, int vb, int c)
{
int a = 0;
int b = 0;
while (b != c)
{
if (b == 0)
{
b = vb;
printf("fill B\n");
}
else if (b < va - a)
{
a += b;
b = 0;
printf("pour B A\n");
}
else
{
b = b - (va - a);
a = 0;
printf("pour B A\n");
if (b != c)
printf("empty A\n");
}
}
printf("success\n");
}
int main()
{
int va, vb, c;
while (scanf("%d%d%d", &va, &vb, &c) != EOF)
doo(va, vb, c);
}
实验
A
题意
判断烷烃基的种类,每一次输入五组数对,代表六个原子间的连接方式。根据输入判断烷烃基的种类。
分析
分析五种同分异构体,发现只有2-methylpentane 和3-methylpentane每个原子与其他原子的连接个数相同。因此,解决过程分为两步。第一步,声明一位数组,存储每个原子的临接原子的数目,并排序,如果对应n-hexane、2,3-dimethylbutane、2,2-dimethylbutane的情况,可直接判断好,如果对应2-methylpentane 、3-methylpentane的情况,则进行下一步。记录下有两个临接原子的标号a,b,如果a与b临接,则为2-methylpentane;反之为3-methylpentane。
代码
#include <algorithm>
#include <iostream>
using namespace std;
int a2[4][6] = {
{1, 1, 2, 2, 2, 2},
{1, 1, 1, 2, 2, 3},
{1, 1, 1, 1, 3, 3},
{1, 1, 1, 1, 2, 4},
};
string jie[4]{"n-hexane", "2-methylpentane 3-methylpentane", "2,3-dimethylbutane", "2,2-dimethylbutane"};
void doo()
{
int a[5];
int b[5];
int find[2];
int num = 0;
for (int i = 0; i < 5; i++)
{
cin >> a[i] >> b[i];
}
int ans[6];
for (int i = 0; i < 6; i++)
{
ans[i] = 0;
}
for (int i = 0; i < 5; i++)
{
ans[a[i] - 1]++;
ans[b[i] - 1]++;
}
for (int i = 0; i < 6; i++)
{
if (ans[i] == 2)
{
find[num] = i + 1;
num++;
}
}
sort(ans, ans + 6);
bool d = 0;
for (int i = 0; i < 4; i++)
{
d = 0;
for (int j = 0; j < 6; j++)
{
if (ans[j] != a2[i][j])
{
d = 1;
}
}
if (d == 0)
{
if (i != 1)
{
cout << jie[i] << endl;
}
else
{
bool dp = 0;
for (int i = 0; i < 5; i++)
{
if (a[i] == find[0] && b[i] == find[1])
{
cout << "2-methylpentane" << endl;
dp = 1;
}
else
{
if (a[i] == find[1] && b[i] == find[0])
{
cout << "2-methylpentane" << endl;
dp = 1;
}
}
}
if (!dp)
{
cout << "3-methylpentane" << endl;
}
}
}
}
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
doo();
}
}
B
题意
输入第一行为n,m,n为题目数量,m为单位罚时。
接下来每一行有m+1列,第一列为name,以后m列为分数。分数有3种情况,第一种为0,代表还没做;第二种为负数,代表出错的次数(还未通过);第三种,一个整数,代表通过所用时间,可能有一个括号,代表出错的次数,计入罚时。
分析
声明string[n+1],类型记录每一个选手的名字和以后每道题的信息。处理每一个string的首字符,如果为0-9之间的数字,则AC数加一。对每一个通过的字符串,使用循环处理成整形数据。如果有括号,则将括号中的数据处理成整形数据。
处理好每个选手的信息后,重载比较,利用sort函数排序,输出。
代码
#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
class p
{
public:
int s;
int t;
string n;
};
bool compare(const p &u, const p &c)
{
if (c.s != u.s)
{
return (u.s < c.s);
}
else
{
if (u.t != c.t)
{
return (u.t > c.t);
}
else
{
return (u.n > c.n);
}
}
}
void doo(const int ops, p *ans, int n, int m, string *a)
{
int atime = 0;
int act = 0;
int s = 0;
for (int i = 1; i < n + 1; i++)
{
if (a[i][0] != '-' && a[i][0] != '0')
{
s++;
int j = 0;
int time = 0;
int ct = 0;
while (j < a[i].length())
{
if (a[i][j] != '(')
{
time = time * 10 + a[i][j] - 48;
}
else
{
break;
}
j++;
}
atime += time;
if (j != a[i].length())
{
j++;
while (a[i][j] != ')')
{
ct = ct * 10 + a[i][j] - 48;
j++;
}
act += ct;
}
}
}
ans[ops].n = a[0];
ans[ops].s = s;
ans[ops].t = atime + act * m;
}
int main()
{
int n, m;
p ans[1000];
cin >> n >> m;
string a[n + 1];
int ops = 0;
while (cin >> a[0])
{
for (int i = 1; i < n + 1; i++)
{
cin >> a[i];
}
doo(ops, ans, n, m, a);
ops++;
}
sort(ans, ans + ops, compare);
for (int i = ops - 1; i >= 0; i--)
{
char *pq = (char *)ans[i].n.c_str();
printf("%-10s %2d %4d\n", pq, ans[i].s, ans[i].t);
}
}
C
题意
简单模拟。
模拟打牌,只是模拟发牌之后的排牌过程,多组数据,以#结尾。
输入
CTCAH8CJD4C6D9SQC7S5HAD2HJH9CKD3H6D6D7H3HQH4C5DKHKS9
SJDTS3S7S4C4CQHTSAH2D8DJSTSKS2H5D5DQDAH7C9S8C8S6C2C3
对于一组数据,第一行为N、E、S、W四种之一,表示由哪个方向的玩家进行发牌,发牌第一张是发给下家而不是自己,一个注意的点。之后两行,每行52个字符,表示26张排,一张拍的表示为两个字符,如CT,C表示梅花,T表示10,。
要求按照一定顺序将四个人的手牌排序,题目定义牌的顺序介绍:首先,花色是(梅花)<(方片)<(黑桃)<(红桃),(输入时,用C,D,S,H分别表示梅花,方片,黑桃,红桃)。对于牌面的值,我们规定2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A。 即先按花色排大小,同花色按牌面排序。
输出,多组数据之间有一个空行,对于一组数据,从South player:的牌开始按顺序输出,具体形式如下:
South player:
+---+---+---+---+---+---+---+---+---+---+---+---+---+
|6 6|A A|6 6|J J|5 5|6 6|7 7|9 9|4 4|5 5|7 7|9 9|T T|
| C | C | D | D | S | S | S | S | H | H | H | H | H |
|6 6|A A|6 6|J J|5 5|6 6|7 7|9 9|4 4|5 5|7 7|9 9|T T|
+---+---+---+---+---+---+---+---+---+---+---+---+---+
思路
每次读入分成两行,每一张牌由两个字符组成,第一个代表花色,第二个代表数字。定义p类型,扑克牌。声明p[4][13]二维数组。利用循环及取模将内容输入。
读入完成后,进行排序。声明常量数组,将花色和数组按顺序写进常量数组中。对花色和数字的大小比较变为对常量数组中下标的比较。重载p类型的比较函数,sort排序,按规定输出就好了。
代码
#include <algorithm>
#include <iostream>
#include <stdio.h>
using namespace std;
char f[4] = {'C', 'D', 'S', 'H'};
char s[13] = {'2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'};
char fangxiang[4] = {'S', 'W', 'N', 'E'};
string player[4] = {"South player:", "West player:", "North player:", "East player:"};
class p
{
public:
char a; //花色
char b; //数字2
};
bool compare(const p &u, const p &c)
{
int f1, f2;
for (int i = 0; i < 4; i++)
{
if (u.a == f[i])
{
f1 = i;
}
if (c.a == f[i])
{
f2 = i;
}
}
if (f1 != f2)
{
return (f1 < f2);
}
else
{
int s1, s2; //记录数字
for (int i = 0; i < 13; i++)
{
if (u.b == s[i])
{
s1 = i;
}
if (c.b == s[i])
{
s2 = i;
}
}
return s1 < s2;
}
}
void doo(char pep)
{
string s1;
string s2;
cin >> s1;
cin >> s2;
s1 += s2;
int num = 0;
for (int i = 0; i < 4; i++)
{
if (pep == fangxiang[i])
{
num = i;
break;
}
}
num = (num + 1) % 4;
p all[4][13];
for (int i = 0; i < 104; i = i + 2)
{
int j = i / 2;
int x = j / 4;
int y = (j + num) % 4;
all[y][x].a = s1[i];
all[y][x].b = s1[i + 1];
}
for (int i = 0; i < 4; i++)
{
sort(all[i], all[i] + 13, compare);
}
for (int i = 0; i < 4; i++)
{
cout << player[i] << endl;
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl;
for (int j = 0; j < 13; j++)
{
cout << "|" << all[i][j].b << " " << all[i][j].b;
}
cout << "|" << endl;
for (int j = 0; j < 13; j++)
{
cout << "|"
<< " " << all[i][j].a << " ";
}
cout << "|" << endl;
for (int j = 0; j < 13; j++)
{
cout << "|" << all[i][j].b << " " << all[i][j].b;
}
cout << "|" << endl;
cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" << endl;
}
cout << endl;
}
int main()
{
char pep;
cin >> pep;
while (pep != '#')
{
doo(pep);
cin >> pep;
}
}