复习一下算法

扫雷游戏


 我的算法不厉害
所以先从简单的题目开始写

思路:准备,首先准备一个方向数组,以中心点遍历周围的八个点。
然后遍历整个二维数组,遇到‘*’就遍历整个方向数组.
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;
}
 

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白色的风扇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值