2018年北京信息科技大学第十届程序设计竞赛暨ACM选拔赛

A-PUBG

题意:从出发位置到目标位置遇到的敌人数量最少。
BFS+优先队列(板子题。。。wa两发忘了memset了)

#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstring>
using namespace std;
const int N = 101;
int n,a[N][N],px,py,dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
bool vis[N][N];
struct node{
    int x,y,cost;
    friend bool operator < (node n1,node n2){
        return n1.cost > n2.cost;
    }
};

int bfs(int x,int y)
{
    priority_queue<node> q;
    node cur,nxt;
    cur.x = x,cur.y = y, cur.cost = 0;
    q.push(cur);
    while(!q.empty())
    {
        cur = q.top();
        q.pop();
        if(cur.x == px&&cur.y == py)
            return cur.cost;
        for(int i = 0; i < 4; ++i){
            nxt.x = cur.x + dir[i][0];
            nxt.y = cur.y + dir[i][1];
            if(nxt.x<0||nxt.y>=n||nxt.x>=n||nxt.y<0||vis[nxt.x][nxt.y] == true)
                continue;
            vis[nxt.x][nxt.y] = true;
            nxt.cost = cur.cost + a[nxt.x][nxt.y];
//            printf("%d\n",a[nxt.x][nxt.y]);
            q.push(nxt);
        }
    }
    return -1;
}

int main() {
//    freopen("in.txt","r",stdin);
    while(~scanf("%d",&n))
    {
        int tx,ty;
        memset(a,0, sizeof(a));
        memset(vis,0, sizeof(vis));
        for(int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                scanf("%d", &a[i][j]);
                if (a[i][j] == -1)
                    tx = i, ty = j,vis[i][j] = true;
                if (a[i][j] == -2)
                    px = i, py = j;
            }
        }
        int ans = bfs(tx,ty);
        printf("%d\n",ans+2);
    }
    return 0;
}

B-precise math function

题意:求n的π次方
签到题。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstring>
using namespace std;

int main()
{
    int t,n,x;
    cin>>t;
    while(t--)
    {
        cin>>n>>x;
        printf("%.*f\n",x,pow(n,acos(-1)));
    }
}

C-颜料的混合

咳咳,恕蒻不会(挠头

D-打篮球

题意:三个人两两打篮球,给出每一轮的胜者序列,问是否满足。
按题意模拟即可,当时蒻蒻很气的写出了所有情况,代码很冗长,就给大家看一个好看一些的吧~

#include <bits/stdc++.h>

using namespace std;

int main ()
{
    int n,op;
    while (cin >> n) {
        int vis[10] = {0};
        vis[1] = 1;
        vis[2] = 1;
        bool flag = true;
        for (int i = 0;i < n;++i) {
            cin >> op;
            if (!vis[op]) {
                flag = false;
            }
            for (int j = 1;j <= 3;++j) {
                if (j != op) {
                    if (vis[j] == 1) vis[j] = 0;
                    else if (vis[j] == 0) vis[j] = 1;
                }
            }
        }
        if (flag) puts("YES");
        else printf("NO\n");
    }
    return 0;
}

E-233

题意:两数相乘。
java大数,Python,c++高精度皆可,这里蒻用的java大数。

import java.util.Scanner;
import java.math.BigInteger;

public class Main {
    public static void main(String[]args){
        Scanner in = new Scanner(System.in);
        int t = in.nextInt();
        for(int i = 0 ; i < t; ++i){
            BigInteger x1 = in.nextBigInteger();
            BigInteger x2 = in.nextBigInteger();
            System.out.println(x1.multiply(x2));
        }
        in.close();
    }
}

F-扫雷
很迷的一题。。。
题意:先给出n×m地图,然后k次点击,(给出x,y坐标),如果点到雷就直接输出在第几步死的,然后结束,否则输出最后一步后的地图情况。
蒻的解法是如果点到的是点点,那么就按照扫雷的规则,将那一块联通块全都涂成0,如果碰到雷就记住第几步即可。(记住千万不要就此结束比如break或者return 0了,后面可能还有数据)最后如果没踩雷就输出地图即可。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstring>
using namespace std;
const int N = 501;
char a[N][N];
bool vis[N][N];
int nxt[8][2] = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}},n,m;
void dfs(int x,int y)
{
    a[x][y] = '0';
    vis[x][y] = true;
    for(int i = 0; i < 8; ++i){
        int tx = x + nxt[i][0];
        int ty = y + nxt[i][1];
        if(a[tx][ty]=='*'||tx<0||tx>=n||ty<0||ty>=m||vis[tx][ty]==true) continue;
        dfs(tx,ty);
    }
}

int main() {
//    freopen("in.txt","r",stdin);
    int t,k;
    cin>>t;
    while(t--){
        memset(vis,0, sizeof(vis));
        scanf("%d%d%d",&n,&m,&k);
        for(int i = 0; i < n; ++i){
            for(int j = 0; j < m; ++j){
                scanf(" %c",&a[i][j]);
            }
        }
        int x,y,ans = -1;
        for(int i = 0; i < k; ++i){
            scanf("%d%d",&x,&y);
            if(a[x-1][y-1]=='*'&&ans==-1){
                ans = i+1;
            }
            if(a[x-1][y-1]=='.') dfs(x-1,y-1);
            vis[x-1][y-1] = true;
        }
        if(ans==-1) {
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < m; ++j) {
                    if (vis[i][j])
                        printf("%c", a[i][j]);
                    else
                        printf("%c", '.');
                }
                puts("");
            }
        }else{
            printf("Game over in step %d\n",ans);
        }
    }
    return 0;
}

但是,令蒻想不到的是,居然又是蒻想多了,根本不需要涂联通块,直接将点到的点点变成0就行了。
29行代码!!(心累)

#include <iostream>
#include <cstdio>
using namespace std;
int n,m,k,t;
char a[501][501];
int main()
{
    cin>>t;
    while(t--){
        cin>>n>>m>>k;
        for(int i = 0; i < n; ++i)
            for(int j = 0; j < m; ++j)
            scanf(" %c",&a[i][j]);
        int x,y,ans = -1;
        for(int i = 0; i < k; ++i){
            cin>>x>>y;
            x--,y--;
            if(a[x][y]=='*'&&ans==-1) ans = i+1;
            if(a[x][y]=='.') a[x][y] = '0';
        }
        if(ans==-1){
            for(int i = 0; i < n; ++i)
                for(int j = 0; j < m; ++j)
                    putchar(a[i][j]);
                puts("");
        }else{
            printf("Game over in step %d\n",ans);
        }
    }
    return 0;
}

G-火车上的2连座

题意:一排4座,中间隔开,求不被隔开的2连座(优先前排的,如果前排多解,优先左排),将其涂为’+’。
所以按题意模拟即可。。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1001;
int n;
char a[N][N];
int main() {
//    freopen("in.txt","r",stdin);
    while(~scanf("%d",&n))
    {
        int flag = 0;
        for(int i = 0; i < n; ++i){
            for(int j = 0; j < 5; ++j){
                scanf(" %c",&a[i][j]);
            }
            if(flag==0&&a[i][0]==a[i][1]&&a[i][1]=='O'){
                flag = 1;
                a[i][0] = a[i][1] = '+';
            }
            if(flag==0&&a[i][3]==a[i][4]&&a[i][3]=='O'){
                flag = 1;
                a[i][3] = a[i][4] = '+';
            }
        }
        if(flag){
            puts("YES");
            for(int i = 0; i < n; ++i){
                for(int j = 0; j < 5; ++j)
                    printf("%c",a[i][j]);
                putchar('\n');
            }
        }else{
            puts("NO");
        }
    }
    return 0;
}

H-程序员的好印象
这道题如果读懂题,其实也是签到题。。
题意:求最长上升子序列(但记住是大于等于),比如0 0 1 0 1 1 0 1,答案是0 0 1 1 1 1(长度为6)

#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1001;
int n,a[101];
int inf = 0x3f;
int dp[101];
int main() {
//    freopen("in.txt","r",stdin);
    while(~scanf("%d",&n))
    {
        for(int i = 0; i < n; ++i){
            scanf("%d",&a[i]);
        }
        memset(dp,inf, sizeof(dp));
        for(int i = 0; i < n; ++i){
            *upper_bound(dp,dp+n,a[i]) = a[i];
        }
        int cnt = upper_bound(dp,dp+n,inf) - dp;
        printf("%d\n",cnt);
    }
    return 0;
}

I题和J题就不不补~(≧▽≦)/~啦啦啦

猜你喜欢

转载自blog.csdn.net/eternally831143/article/details/80208246