SDUT - 2017年寒假集训 阶段测试赛3(组队)解题报告

2017-02-20 1,329 次浏览 解题报告

比赛 ID: 2015

注:本题解参考代码均为 C++ 代码,如果你是 C 使用者,出现不认识的头文件时,若是 c 开头的,一般可以通过去掉开头的 c 然后在末尾添加 .h 来转换成 C 的头文件,如 cstdio 在 C 中为 stdio.h ,其他的请自行搜索。另外,如果出现不认识的写法,如 sort(排序)stack(栈) 等,请自行实现。


A - SDUT 2413 n a^o7 !

签到题。逆序遍历一遍字符串,根据对应规则输出即可。

参考代码:

#include <cstdio>
#include <cstring>
using namespace std;

int main(int argc, char const *argv[]) {
    int t;
    char str[101];
    scanf("%d%*c", &t);
    for(int l=1; l<=t; ++l) {
        gets(str);
        printf("Case %d: ", l);
        for(int i=strlen(str)-1; i>=0; --i) {
            if(str[i] == '!') putchar('i');
            else if(str[i] == 'u') putchar('n');
            else if(str[i] == 'n') putchar('u');
            else if(str[i] == 'a') putchar('e');
            else if(str[i] == 'e') putchar('a');
            else if(str[i] == 'p') putchar('d');
            else if(str[i] == '7') putchar('l');
            else if(str[i] == '^') putchar('v');
            else if(str[i] == 'w') putchar('m');
            else if(str[i] == '5') putchar('s');
            else putchar(str[i]);
        }
        putchar('\n');
    }
    
    return 0;
}

B - SDUT 2777 小P的故事——神奇的换零钱

典型的完全背包装满方案数的题,我们可以看做有 3 种物品,重量分别为 1, 2, 3,背包容量为钱数 N,装满背包的方案数就是此题的答案。

具体算法推荐学习这篇博客:背包问题——“01背包”及“完全背包”装满背包的方案总数分析及实现

参考代码:

#include <cstdio>
using namespace std;

const int MAXC = 32767;
const int MAXN = 3;

int main(int argc, char const *argv[]) {
    int n, w[MAXN+1] = {0, 1, 2, 3,}, dp[MAXC+1] = {0};
    dp[0] = 1;
    for(int i=1; i<=MAXN; ++i) {
        for(int j=w[i]; j<=MAXC; ++j) {
            dp[j] += dp[j-w[i]];
        }
    }
    while(~ scanf("%d", &n)) {
        printf("%d\n", dp[n]);
    }
    
    return 0;
}

C - SDUT 1576 魔幻数字47

直接从 l 遍历 到 r,判断余数是否为 47 即可,注意负数取模的情况。

参考代码:

#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;

int main(int argc, char const *argv[]) {
    int n, l, r;
    scanf("%d", &n);
    while(n--){
        scanf("%d %d", &l, &r);
        if(l > r) swap(l, r);
        bool has = false;
        for(int i=l; i<=r; ++i) {
            if(abs(i%100) == 47) {
                printf("%d\n", i);
                has = true;
            }
        }
        if(!has) printf("NONE\n");
    }
    
    return 0;
}

D - SDUT 1025 棋盘问题

可以 DFS 一下,并利用回溯标记行列有没有用过,数量到 k 时记录答案。

参考代码:

#include <cstdio>
#include <cstring>
using namespace std;

int n, k, ans;
char graph[8][9];
bool vis_r[8], vis_c[8];

void DFS(int r, int num) {
    if(num == k) { // 数量到 k,记录答案并返回
        ans++;
        return;
    }
    for(int i=r; i<n; ++i) { // 从当前行开始向下枚举行
        for(int j=0; j<n; ++j) { // 枚举列
            if(graph[i][j]=='#' && !vis_r[i] && !vis_c[j]) { // 符合条件
                vis_r[i] = vis_c[j] = true; // 标记此行列已用过
                DFS(i, num+1);
                vis_r[i] = vis_c[j] = false; // 回溯取消标记
            }
        }
    }
}

int main(int argc, char const *argv[]) {
    while(scanf("%d %d", &n, &k), ~n|~k) {
        memset(vis_r, false, sizeof(vis_r));
        memset(vis_c, false, sizeof(vis_c));
        for(int i=0; i<n; ++i) {
            scanf("%s", graph[i]);
        }
        ans = 0;
        DFS(0, 0);
        printf("%d\n", ans);
    }
    
    return 0;
}

E - SDUT 3253 Game!

简单博弈,后手只需要跟着先手镜像取石子即可。

如果先手取完后剩余奇数个,则后手取对称位置的 1 个石子,否则后手取对称位置的 2 个石子,总能使先手必输。

只有当 n <= 2 先手可以一次取完时,先手才必胜。

参考代码:

#include <cstdio>
using namespace std;

int main(int argc, char const *argv[]) {
    int t;
    long long n;
    scanf("%d", &t);
    while(t--){
        scanf("%lld", &n);
        if(n > 2) printf("blankcqk\n");
        else printf("zbybr\n");
    }
    
    return 0;
}

F - SDUT 2930 人活着系列之开会

多源最短路问题。把每个岛的字母编号映射成数字就可以和普通最短路一样处理了,注意可能有重边。

参考代码:

#include <cstdio>
#include <algorithm>
using namespace std;

const int MAX = 52;
const int INF = 0x3f3f3f3f;

int dis[MAX][MAX];

int GetIdx(char ch) {
    if(ch>='A' && ch<='Z') return ch-'A';
    else return ch-'a'+26;
}

void Floyd() {
    for(int k=0; k<MAX; ++k) {
        for(int i=0; i<MAX; ++i) {
            for(int j=0; j<MAX; ++j) {
                if(dis[i][k]+dis[k][j] < dis[i][j])
                    dis[i][j] = dis[i][k]+dis[k][j];
            }
        }
    }
}

int main(int argc, char const *argv[]) {
    int n, d;
    char s1[2], s2[2];
    for(int i=0; i<MAX; ++i) { // 初始化
        for(int j=0; j<MAX; ++j) {
            dis[i][j] = INF;
        }
        dis[i][i] = 0;
    }
    scanf("%d", &n);
    for(int i=0; i<n; ++i) {
        scanf("%s %s %d", s1, s2, &d);
        if(d < dis[GetIdx(s1[0])][GetIdx(s2[0])]) // 坑:可能有重边
            dis[GetIdx(s1[0])][GetIdx(s2[0])] = dis[GetIdx(s2[0])][GetIdx(s1[0])] = d;
    }
    Floyd();
    int min_dis = INF, idx = -1;
    for(int i=0; i<GetIdx('Z'); ++i) { // 找 A-Y 到 Z 的最短路中的最小值
        if(dis[i][GetIdx('Z')] < min_dis) {
            min_dis = dis[i][GetIdx('Z')];
            idx = i;
        }
    }
    printf("%c %d\n", idx+'A', min_dis);
    
    return 0;
}

G - SDUT 2778 小明的花费预算

请参考这篇博客


H - SDUT 2162 The Android University ACM Team Selection Contest

稍复杂的模拟题,按题意模拟即可。

参考代码:

#include <cstdio>
#include <algorithm>
using namespace std;

struct info {
    char name[31];
    int A;
    int T;
    int P;
    int idx;
} a[10000], b[10000];

int cmp1(info a, info b) {
    if(a.T != b.T) return a.T > b.T;
    else return a.P < b.P;
}

int cmp2(info a, info b) {
    return a.idx < b.idx;
}

int main(int argc, char const *argv[]) {
    int c, n, m;
    scanf("%d", &c);
    for(int i=1; i<=c; ++i) {
        if(i > 1) printf("\n");
        printf("Case %d:\n", i);
        int cnt = 0;
        scanf("%d %d", &n, &m);
        for(int j=0; j<n; ++j) {
            scanf("%s %d %d %d", a[j].name, &a[j].A, &a[j].T, &a[j].P);
            a[j].idx = j;
            if(a[j].T) cnt++;
        }
        if(cnt < m) {
            for(int j=0; j<n; ++j) {
                printf("%s\n", a[j].name);
            }
        }
        else {
            sort(a, a+n, cmp1);
            bool has_all_girl = false, found = false;
            for(int j=0; j<m; ++j) {
                if(a[j].A) has_all_girl = true;
            }
            if(!has_all_girl) {
                for(int j=m; j<cnt; ++j) {
                    if(a[j].A) {
                        a[m] = a[j];
                        found = true;
                        break;
                    }
                }
            }
            if(found) {
                sort(a, a+m+1, cmp2);
                for(int j=0; j<m+1; ++j) {
                    printf("%s\n", a[j].name);
                }
            }
            else {
                sort(a, a+m, cmp2);
                for(int j=0; j<m; ++j) {
                    printf("%s\n", a[j].name);
                }
            }
        }
    }
    
    return 0;
}

bLue 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。
本文地址:https://dreamer.blue/blog/post/2017/02/20/sdut-c2015.dream

还不快抢沙发

添加新评论