扫雷游戏
我的算法不厉害
所以先从简单的题目开始写
思路:准备,首先准备一个方向数组,以中心点遍历周围的八个点。
然后遍历整个二维数组,遇到‘*’就遍历整个方向数组.
int tx = i + dx[k];
int ty = j + dy[k];
如果遇到越界的就直接continue
其他的就在一个只有数组的二维数组进行++操作。
这里需要考虑到一点,就是前面会有"*"然后后面也会有'*',这样就是导致*的点多加了,所以最后输出条件是如果大于等于42就输出'*'即可
代码如下:
#include<iostream>
#include<string.h>
using namespace std;
int n, m;
char tmp;
int map[150][150];
int dx[8] = {-1,-1,-1, 0, 0, 1, 1, 1};
int dy[8] = {-1, 0, 1,-1, 1,-1, 0, 1};
int main() {
cin >> n >> m;
memset(map, 0, sizeof(map));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> tmp;
if (tmp == '*') {
for (int k = 0; k < 8; k++) {
int tx = i + dx[k];
int ty = j + dy[k];
if (tx >= 1 && tx <= n && ty >= 1 && ty <= m) {
map[tx][ty]++;
}
}
map[i][j] = '*';
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (map[i][j] >= 42) {
cout << '*';
}
else {
cout << (int)map[i][j];
}
}
cout << endl;
}
return 0;
}
玩具谜题
# [NOIP2016 提高组] 玩具谜题
## 题目背景
NOIP2016 提高组 D1T1
## 题目描述
小南有一套可爱的玩具小人,它们各有不同的职业。
有一天,这些玩具小人把小南的眼镜藏了起来。小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的面朝圈外。如下图:
![](https://cdn.luogu.com.cn/upload/image_hosting/0u7em9pi.png)
这时 singer 告诉小南一个谜题:“眼镜藏在我左数第 $3$ 个玩具小人的右数第 $1$ 个玩具小人的左数第 $2$ 个玩具小人那里。”
小南发现,这个谜题中玩具小人的朝向非常关键,因为朝内和朝外的玩具小人的左右方向是相反的:面朝圈内的玩具小人,它的左边是顺时针方向,右边是逆时针方向;而面向圈外的玩具小人,它的左边是逆时针方向,右边是顺时针方向。
小南一边艰难地辨认着玩具小人,一边数着:
singer 朝内,左数第 $3$ 个是 archer。
archer 朝外,右数第 $1$ 个是 thinker。
thinker 朝外,左数第 $2$ 个是 writer。
所以眼镜藏在 writer 这里!
虽然成功找回了眼镜,但小南并没有放心。如果下次有更多的玩具小人藏他的眼镜,或是谜题的长度更长,他可能就无法找到眼镜了。所以小南希望你写程序帮他解决类似的谜题。这样的谜題具体可以描述为:
有 $n$ 个玩具小人围成一圈,已知它们的职业和朝向。现在第 $1$ 个玩具小人告诉小南一个包含 $m$ 条指令的谜題,其中第 $z$ 条指令形如“向左数/右数第 $s$ 个玩具小人”。你需要输出依次数完这些指令后,到达的玩具小人的职业。
## 输入格式
输入的第一行包含两个正整数 $n,m$,表示玩具小人的个数和指令的条数。
接下来 $n$ 行,每行包含一个整数和一个字符串,以逆时针为顺序给出每个玩具小人的朝向和职业。其中 $0$ 表示朝向圈内,$1$ 表示朝向圈外。保证不会出现其他的数。字符串长度不超过 $10$ 且仅由英文字母构成,字符串不为空,并且字符串两两不同。整数和字符串之间用一个空格隔开。
接下来 $m$ 行,其中第 $i$ 行包含两个整数 $a_i,s_i$,表示第 $i$ 条指令。若 $a_i=0$,表示向左数 $s_i$ 个人;若 $a_i=1$,表示向右数 $s_i$ 个人。 保证 $a_i$ 不会出现其他的数,$1 \le s_i < n$。
## 输出格式
输出一个字符串,表示从第一个读入的小人开始,依次数完 $m$ 条指令后到达的小人的职业。
## 样例 #1
### 样例输入 #1
```
7 3
0 singer
0 reader
0 mengbier
1 thinker
1 archer
0 writer
1 mogician
0 3
1 1
0 2
```
### 样例输出 #1
```
writer
```
## 样例 #2
### 样例输入 #2
```
10 10
1 C
0 r
0 P
1 d
1 e
1 m
1 t
1 y
1 u
0 V
1 7
1 1
1 4
0 5
0 3
0 1
1 6
1 2
0 8
0 4
```
### 样例输出 #2
```
y
```
## 提示
**样例 1 说明**
这组数据就是【题目描述】中提到的例子。
**子任务**
子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试只解决一部分测试数据。
每个测试点的数据规模及特点如下表:
![](https://cdn.luogu.com.cn/upload/image_hosting/7su06u3r.png)
其中一些简写的列意义如下:
- 全朝内:若为 $\surd$,表示该测试点保证所有的玩具小人都朝向圈内;
- 全左数:若为 $\surd$,表示该测试点保证所有的指令都向左数,即对任意的 $1\leq z\leq m, a_i=0$;
- $s=1$:若为 $\surd$,表示该测试点保证所有的指令都只数 $1$ 个,即对任意的 $1\leq z\leq m,s_i=1$;
职业长度为 $1$:若为 $\surd$,表示该测试点保证所有玩具小人的职业一定是一个长度为 $1$ 的字符串。
思路:
在最开始写这个题目时候,我是想建立一个循环数组,但后发现建立不出来,后面发现其实不用循环数组也能写出来。
主要是要明白这个遍历的方向,对于数组来说遍历无非只有两种方式,第一种是向上遍历,第二种就是向下遍历,我们不难发现这个规律,当行为的左右和任务的状态相加只有三种数字,0,1,2。当为1的时候,数组是向下遍历的,所以下标是加上行为的步数,当数字为2的时候,下标是减去行为的数字的。有了这个后面好写很多。
接下就是特殊状态的判断,当向上减去步数的时候,已经为负数的时候,我们要用n加上步数得到下标。当向下加上步数的时候,已经超过了最大步数,我们要用查过的步数来减去n的到下标。
代码如下:
#include<iostream>
#include<string.h>
#include<string>
using namespace std;
int n, m;
struct Person {
int status;
string job;
};
Person jobPerson[100050];
int main() {
cin >> n >> m;
int direction;
int step;
for (int i = 0; i < n; i++) {
cin >> jobPerson[i].status >> jobPerson[i].job;
}
string ans;
int index = 0;
for (int i = 0; i < m; i++) {
cin >> direction >> step;
int tmp = direction + jobPerson[index].status;
if (tmp == 0 || tmp == 2) {
index -= step;
if (index < 0) {
index = n + index;
}
ans = jobPerson[index].job;
}
else if (tmp == 1) {
index += step;
if (index > n - 1) {
index = index - n;
}
ans = jobPerson[index].job;
}
}
cout << ans << endl;
return 0;
}
高精度加法
这个就是模拟我们平时的加法,可能是java写多了,都已经忘记了string最左边的下标为0了,其他的没什么
#include<iostream>
#include<string.h>
#include<string>
using namespace std;
int main() {
string s1;
string s2;
cin >> s1 >> s2;
int len1 = s1.length();
int len2 = s2.length();
if (len1 > len2) {
for (int i = 1; i <= len1 - len2; i++) {
//s2更加短,所以在s2这边补0
s2 = '0' + s2;
}
}
else {
for (int i = 1; i <= len2 - len1; i++) {
s1 = '0' + s1;
}
}
int len = s1.length();
//cf是商,用于向前加数的
int cf = 0;
//temp是余 体现答案的
int temp = 0;
//cf需要注意是算之前,和算之后的,
//算之前 是之前已经加上的值,算之后是一次循环之后需要用到的值
string s;
for (int i = len - 1; i >= 0; i--) {
cf = (s1[i] - '0') + (s2[i] - '0') + cf;
temp = cf % 10;
cf = cf / 10;
s = (char)('0' +temp) + s;
}
if (cf != 0) {
s = (char)('0' + cf) + s;
}
cout << s << endl;
}