【笔试记录】京东 | 20230819 | cpp (思路后续补上)

夹吃棋

题目描述

在一个 3 * 3 的棋盘上,小红和小紫正在玩“夹吃棋”。 所谓“夹吃棋”,即如果存在一个白子,它的两侧 (横向或者纵向)相邻都是黑子,则这个棋子将被“夹吃”,对于黑棋亦然。

如果一个棋盘的局面没有一方被夹吃,或者黑白双方都被对面夹吃,则认为是平局。如果只有一方夹吃了另一方,则认为夹吃方赢,被夹吃方输。

小红执黑棋,小紫执白棋,现在给定一个局面,请你判断当前棋局是谁获胜。

输入描述
第一行输入一个正整数 t (1 <= t <= 10000),代表询问的次数。

接下来每组询问输入三行,,每行是一个长度为3的字符串,字符串仅由’o’,‘.’,'*'组成。

其中 o 代表白棋,* 代表黑棋,. 代表未放置棋子。

输出描述
小红获胜输出“kou”,小紫获胜输出“yukan”,平局输出“draw”。

输入示例

3
...
o*o
...
o**
ooo
..*
o*o
*o*
o*o

输出示例

yukan
kou
draw

思路

为了方便判断,我将字符转换成了int。

#include <bits/stdc++.h>
using namespace std;
 
int t;  // 询问次数
int m[3][3];  // 0-未放置;1-'*';-1-'o'
 
int main(){
    string s;
    cin >> t;
    while(t--){
        for(int i = 0; i < 3; i++){
            s.clear();
            cin >> s;
            for(int j = 0; j < 3; j++){
                if(s[j] == '.') m[i][j] = 0;
                else if(s[j] == '*') m[i][j] = 1;
                else if(s[j] == 'o') m[i][j] = -1;
            }
        }
         
        int flag_kou = 0;
        int flag_yukan = 0;
        for(int i = 0; i < 3; i++){
            if(m[i][1] != 0 && (m[i][1] + m[i][0]) == 0 && (m[i][1] + m[i][2]) == 0){
                if(m[i][1] == 1) flag_yukan = 1;
                else if(m[i][1] == -1) flag_kou = 1;
            }
            if(m[1][i] != 0 && (m[1][i] + m[0][i]) == 0 && (m[1][i] + m[2][i]) == 0){
                if(m[1][i] == 1) flag_yukan = 1;
                else if(m[1][i] == -1) flag_kou = 1;
            }
        }
         
        if(flag_kou == 1 && flag_yukan == 0) cout << "kou" << endl;
        else if(flag_kou == 0 && flag_yukan == 1) cout << "yukan" << endl;
        else cout << "draw" << endl;
    }
    return 0;
}

小红买药

题目描述

小红准备买药治病。已知共有 n 种症状和 m 种药,第 i 种药可以治疗一些症状,但可能会导致一些副作用,添加一些新的症状。小红依次服用了一些药,请你告诉小红,当她每次服用一副药时,当前还有多少症状?

输入描述

  1. 第一行输入一个正整数 n(1 <= n <= 20),代表症状的数量
  2. 第二行输入一个长应为 n 的 01 串,第 i 位是 “1” 代表小红目前有第 i 个症状,第i位是 “0” 代表没有该症状。
  3. 第三行输入一个正整数 m( 1<= m <= 10^4),代表药的数量。
  4. 接下来的 2 * m 行,每 2 行描述一副药:
  • 第一行输入一个长度为 n 的 01 串,代表该药能治疗的症状。’1‘代表可以治疗,‘0’代表不能治疗。
  • 第二行输入一个长度为 n 的 01 串,代表该药会产生的副作用。’1‘代表会产生该症状,’0‘代表不会产生。
  1. 接下来的一行,输入一个正整数 q( 1<= q <= 10^4),代表小红服用的药数量。
  2. 接下来的 q 行,每行输入一个正整数 u(1 <= ai, u <= m),代表小红服用了第 u 副药。

保证每副药的副作用产生的症状和该药治疗的症状是不会重复的,即不会存在同一个位置的两个 01 串都是‘1’。

输出描述
输出 q 行,每行输入一个正整数,代表当前小红服用药后,身体有多少症状。

输入示例

4
0101
3
1100
0010
0101
1000
1001
0000
3
2
3
1

输出示例

1
0
1

思路

注意接收数据的时候会遗漏“0”

#include <bits/stdc++.h>
using namespace std;

#define N 20
#define M 10004
int n;  // 症状的数量
int zz[N];  // 当前症状情况
int m;  // 药的数量
int zl[M][N];    // 治疗功能
int fzy[M][N];  // 副作用
int q;  // 服用药的数量
int idx;  // 当前服用药的index

int main(){
    cin >> n;
    char c;
    for(int i = 0; i < n; i++){
        cin >> c;
        if(c=='0')zz[i] = 0;
        else zz[i] = 1;
    }
    cin >> m;
    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            cin >> c;
            if(c == '0') zl[i][j] = 0;
            else zl[i][j] = 1;
        }
        for(int j = 0; j < n; j++){
            cin >> c;
            if(c == '0') fzy[i][j] = 0;
            else fzy[i][j] = 1;
        }
    }
    cin >> q;
    
    while(q--){
        cin >> idx;
        idx--;
        int count = 0;
        for(int i = 0; i < n; i++){
            if(zl[idx][i] == 1) zz[i] = 0;   // 如果这副药能治愈第i种症状,无论有没有症状,吃下一定是无症状
            // 考虑副作用
            if(fzy[idx][i] == 1) zz[i] = 1;
            if(zz[i] == 1) count++;
        }
        cout << count << endl;
    }
    return 0;
}

皇后移动的最小步数

题目描述

有一个 n 行 m 列的棋盘,有一些格子是障碍物不能通过。

小红控制一个皇后在从左上角出发,每次移动她可以控制皇后进行以下三种方式中的一种:

  1. 向右移动若干个格子。

  2. 向下移动若干个格子。

  3. 向右下移动若干个格子。

用数学语言描述,当前的坐标在 (x, y) 时,每次移动可以到 (x + k, y) 或 (x, y + k) 或 (x + k, y + k) 其中 k 为任意正整数。移动的前提是,路径上没有障碍物。 小红想知道,皇后从左上角移动到右下角,最少要移动多少步?

输入描述
第一行输入两个正整数 n 和 m(1 <= n,m <= 2000),代表行数和列数。

接下来的 n 行,每行输入一个长度 m 的字符串,用来表示棋盘。

其中 “.” 代表可以通过的位置,“*” 代表障碍物。 保证左上角和右下角都不是障碍物。

输出描述
如果无法到达,请输出-1。

否则输出一个整数,代表最少的移动次数。

输入示例

4 5
...*.
*..**
.....
.....

输出示例

2

思路

BFS

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

struct State {
    int x, y, steps;
};

int main() {
    int n, m;
    cin >> n >> m;
    vector<string> board(n);
    for (int i = 0; i < n; ++i) {
        cin >> board[i];
    }
    
    if (board[0][0] == '*' || board[n-1][m-1] == '*') {
        cout << -1 << endl;
        return 0;
    }

    vector<vector<bool>> visited(n, vector<bool>(m, false));
    queue<State> q;
    q.push({0, 0, 0});
    visited[0][0] = true;

    while (!q.empty()) {
        State curr = q.front();
        q.pop();

        if (curr.x == n - 1 && curr.y == m - 1) {
            cout << curr.steps << endl;
            return 0;
        }

        // Three possible directions
        // Right
        for (int k = 1; curr.y + k < m; ++k) {
            if (board[curr.x][curr.y + k] == '*') break;
            if (!visited[curr.x][curr.y + k]) {
                visited[curr.x][curr.y + k] = true;
                q.push({curr.x, curr.y + k, curr.steps + 1});
            }
        }
        // Down
        for (int k = 1; curr.x + k < n; ++k) {
            if (board[curr.x + k][curr.y] == '*') break;
            if (!visited[curr.x + k][curr.y]) {
                visited[curr.x + k][curr.y] = true;
                q.push({curr.x + k, curr.y, curr.steps + 1});
            }
        }
        // Diagonal
        for (int k = 1; curr.x + k < n && curr.y + k < m; ++k) {
            if (board[curr.x + k][curr.y + k] == '*') break;
            if (!visited[curr.x + k][curr.y + k]) {
                visited[curr.x + k][curr.y + k] = true;
                q.push({curr.x + k, curr.y + k, curr.steps + 1});
            }
        }
    }

    cout << -1 << endl;
    return 0;
}

DP(超时)

#include <iostream>
#include <vector>
using namespace std;

const int INF = 4e6;
int n, m;   // 行数。列数

int main(){
    cin >> n >> m;
    vector<vector<char>> grid(n, vector<char>(m));
    
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            cin >> grid[i][j];
        }
    }
    
    vector<vector<int>> dp(n, vector<int>(m, INF));
    dp[0][0] = 0;
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(grid[i][j] == '*') continue;
            // 分三种情况:
            // 向下移动
            for(int k = i+1; k < n; k++){
                dp[k][j] = min(dp[k][j], dp[i][j]+1);
            }
            // 向右移动
            for(int k = j+1; k < m; k++){
                dp[i][k] = min(dp[i][k], dp[i][j]+1);
            }
            // 向右下移动
            for(int k = 1; i+ k < n && j + k < m; k++){
                dp[i+k][j+k] = min(dp[i+k][j+k], dp[i][j]+1);
            }
        }
    }
    if(dp[n-1][m-1] == INF) cout << -1 << endl;
    else cout << dp[n-1][m-1] << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值