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

点击查看题目

别人学校的ACM选拔赛,所以题对练过ACM的比较简单。至少7道可以轻松A过。

A-PUBG(简单搜索)

/**
Author Ms. Wen
Date 2018/5/5

解题思路:用优先队列进行广搜,如果第二次
到达某点遇到敌人更少,则该点可再次进队。
**/
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 200;
typedef long long ll;
int Map[maxn][maxn];
int vis[maxn][maxn];
int n;
int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
struct Node {
    int x,y;
    ll num;
    friend bool operator<(Node a,Node b) {
        return a.num>b.num;
    }
};
int sx,sy,ex,ey;
int bfs() {
    Node cur,nex;
    priority_queuequ;
    memset(vis,-1,sizeof(vis));
    cur.x = sx;
    cur.y = sy;
    cur.num = 0;
    vis[sx][sy] = 0;
    qu.push(cur);
    while(!qu.empty()) {
        cur = qu.top();
        qu.pop();
        if(cur.x == ex && cur.y == ey) {
            return cur.num;
        }
        for(int i = 0; i < 4; i++) {
            nex.x = cur.x + dir[i][0];
            nex.y = cur.y + dir[i][1];
            if(nex.x>=1 && nex.x<=n && nex.y>=1 && nex.y<=n) {
                if(vis[nex.x][nex.y]==-1) {
                    nex.num = cur.num + Map[nex.x][nex.y];
                    vis[nex.x][nex.y] = nex.num;
                    qu.push(nex);
                }
                else if(cur.num+Map[nex.x][nex.y] < vis[nex.x][nex.y]) {
                    nex.num = cur.num + Map[nex.x][nex.y];
                    vis[nex.x][nex.y] = nex.num;
                    qu.push(nex);
                }
            }
        }
    }
    return -1;
}
int main() {
    while(~scanf("%d",&n)) {
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                scanf("%d",&Map[i][j]);
                if(Map[i][j]==-1) {
                    sx = i;
                    sy = j;
                    Map[i][j] = 0;
                }
                if(Map[i][j]==-2) {
                    ex = i;
                    ey = j;
                    Map[i][j] = 0;
                }
            }
        }
        int ans = bfs();
        printf("%d\n",ans);
    }
    return 0;
}

B-precise math function(签到题)

/***************
Author Ms. Wen
Date 2018/5/5

使用数学函数,需要注意的是,对于PI的取值,最好使用
库中的值,或用acos(-1)求,自己手敲3.14...会精度丢失。
******************/
#include 
#include 
#include 
#include 

using namespace std;

int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        int n,x;
        scanf("%d%d",&n,&x);
        double pi = acos(-1);
        double ans = pow(n,pi);
        if(x == 1) {
            printf("%.1lf\n",ans);
        }
        else if(x == 2) {
            printf("%.2lf\n",ans);
        }
        else if(x == 3) {
            printf("%.3lf\n",ans);
        }
        else if(x == 4) {
            printf("%.4lf\n",ans);
        }
        else if(x == 5) {
            printf("%.5lf\n",ans);
        }
        else {
            printf("%.6lf\n",ans);
        }
    }
    return 0;
}

C-颜料的混合

/*********************
Author Ms. Wen
Date 2018/5/5

解题思路:
这个题目当时没写出来,它是只要给出的点,在三角内部即可。
因为对于(x1,y1),(x2,y2),其连线上的任意一点都可以构成。
同理(x1,y1),(x3,y3),其连线上的任意一点都可由这两点分量
构成。线段上的任意点又可和线段上的任意点相连,其中间的点
又可以被构成。则只要给出的点在三角形内即可。很巧妙,当时
真的没想到和三角形与点的位置这个知识点扯上关系。
***************************/
#include 
#include 
#include 
#include 
#define eps 1e-5

using namespace std;

int Area(int x1,int y1,int x2,int y2,int x3,int y3) {
    int area = x1*y2 + x2*y3 + x3*y1 - x1*y3 - x2*y1 - x3*y2;
    return abs(area);
}
bool check(int x0,int y0,int x1,int y1,int x2,int y2,int x3,int y3) {
    int area1 = Area(x0,y0,x1,y1,x2,y2);
    int area2 = Area(x0,y0,x1,y1,x3,y3);
    int area3 = Area(x0,y0,x2,y2,x3,y3);
    int sum = Area(x1,y1,x2,y2,x3,y3);
    if(area1+area2+area3 == sum) {
        return true;
    }
    return false;
}
int main() {
    int x0,y0,x1,y1,x2,y2,x3,y3;
    while(~scanf("%d%d%d%d%d%d%d%d",&x0,&y0,&x1,&y1,&x2,&y2,&x3,&y3)) {
        if(check(x0,y0,x1,y1,x2,y2,x3,y3)) {
            printf("Yes\n");
        }
        else {
            printf("No\n");
        }
    }
    return 0;
}

D-打篮球(签到题)

/**
直接模拟即可。
**/
#include 
#include 
#include 

using namespace std;

const int maxn = 200;
int arr[maxn];
int main() {
    int n;
    while(~scanf("%d",&n)) {
        for(int i = 1; i <= n; i++) {
            scanf("%d",&arr[i]);
        }
        int p1 = 1,p2 = 2,watch=3,tmp;
        bool flag = true;
        for(int i = 1; i <= n; i++) {
            if(arr[i]==watch) {
                flag = false;
                break;
            }
            //p1赢,则p2下场。
            if(arr[i] == p1) {
                tmp = p2;
                p2 = watch;
                watch = tmp;
            }
            else {
                tmp = p1;
                p1 = watch;
                watch = tmp;
            }
        }
        if(flag) {
            printf("YES\n");
        }
        else {
            printf("NO\n");
        }
    }
    return 0;
}

E-233(大数乘法)

/**
偷懒,用Java过了一发。
**/
import java.math.BigInteger;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        int t;
        Scanner input = new Scanner(System.in);
        t = input.nextInt();
        while(t != 0) {
            BigInteger a = BigInteger.ZERO;
            BigInteger b = BigInteger.ZERO;
            a = input.nextBigInteger();
            b = input.nextBigInteger();
            a = a.multiply(b);
            System.out.println(a);
            t--;
        }
    }
}

F--扫雷(搜索)

#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 510;
char Map[maxn][maxn];
int vis[maxn][maxn];
char ans[maxn][maxn];
int n,m,k;
int dir[8][2] = {{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
struct Node {
    int x;
    int y;
};
void bfs(int x,int y) {
    Node cur,nex;
    queuequ;
    ans[x][y] = Map[x][y];
    if(Map[x][y] == '.') {
        ans[x][y] = '0';
    }
    vis[x][y] = 1;
    cur.x = x;
    cur.y = y;
    qu.push(cur);
    while(!qu.empty()) {
        cur = qu.front();
        qu.pop();
        for(int i = 0; i < 8; i++) {
            nex.x = cur.x + dir[i][0];
            nex.y = cur.y + dir[i][1];
            if(nex.x>=1&&nex.x<=n&&nex.y>=1&&nex.y<=m&&vis[nex.x][nex.y]==0) {
                ans[nex.x][nex.y] = Map[nex.x][nex.y];
                if(Map[nex.x][nex.y]=='.') {
                    ans[nex.x][nex.y] = '0';
                }
                vis[nex.x][nex.y] = 1;
                qu.push(nex);
            }
        }
    }
}
int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d%d",&n,&m,&k);
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                scanf(" %c",&Map[i][j]);
                ans[i][j] = '.';
            }
        }
        memset(vis,0,sizeof(vis));
        int x,y;
        bool flag = true;  //代表没有踩到雷。
        for(int i = 1; i <= k; i++) {
            scanf("%d%d",&x,&y);
            if(flag) {
                if(Map[x][y]=='*') {
                    printf("Game over in step %d\n",i);
                    flag = false;
                }
                else if(vis[x][y]==0) {
                    bfs(x,y);
                }
            }
        }
        if(flag) {
            for(int i = 1; i <= n; i++) {
                for(int j = 1; j <= m; j++) {
                    printf("%c",ans[i][j]);
                }
                printf("\n");
            }
        }
    }
    return 0;
}

G-火车上的2连座(签到题)

#include 
#include 
#include 
 
using namespace std;
 
const int maxn = 1010;
char sit[maxn][10];
int main() {
    int n;
    while(~scanf("%d",&n)) {
        bool flag = false;
        for(int i = 1; i <= n; i++) {
            scanf("%s",sit[i]);
            if(!flag) {
                if(sit[i][0]=='O' && sit[i][1]=='O') {
                    sit[i][0] = sit[i][1] = '+';
                    flag = true;
                }
            }
            if(!flag) {
                if(sit[i][3]=='O' && sit[i][4]=='O') {
                    sit[i][3] = sit[i][4] = '+';
                    flag = true;
                }
            }
        }
        if(flag) {
            printf("YES\n");
            for(int i = 1; i <= n; i++) {
                puts(sit[i]);
            }
        }
        else {
            printf("NO\n");
        }
    }
    return 0;
}

H-程序员的好印象(简单动态规划)

#include 
#include 
#include 
#include 
 
using namespace std;
 
const int maxn = 200;
 
int dp[maxn][2];
int arr[maxn];
int main() {
    int n;
    while(~scanf("%d",&n)) {
        for(int i = 1; i <= n; i++) {
            scanf("%d",&arr[i]);
        }
        memset(dp,0,sizeof(dp));
        if(arr[1]==0) {
            dp[1][0] = 1;
            dp[1][1] = 0;
        }
        else {
            dp[1][0] = 0;
            dp[1][1] = 1;
        }
        for(int i = 2; i <= n; i++) {
            if(arr[i]==0) {
                dp[i][0] = dp[i-1][0] + 1;
                dp[i][1] = dp[i-1][1];
            }
            else {
                dp[i][1] = max(dp[i-1][0]+1,dp[i-1][1]+1);
                dp[i][0] = dp[i-1][0];
            }
        }
        int ans = max(dp[n][0],dp[n][1]);
        printf("%d\n",ans);
    }
}

I-郊游


J-过河(积分)

2018年北京信息科技大学第十届程序设计竞赛暨ACM选拔赛题目题解_第1张图片

#include 
#include 
#include 
#include 

using namespace std;

int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        int s,v1,v2;
        scanf("%d%d%d",&s,&v1,&v2);
        if(s == 0) {
            printf("%.10lf\n",0.0);
        }
        else if(v1 <= v2) {
            printf("Infinity\n");
        }
        else {
            double ans = (v1*s)*1.0/(v1*v1-v2*v2);
            printf("%.10lf\n",ans);
        }
    }
    return 0;
}


你可能感兴趣的:(ACM_比赛题解)