比赛 ID: 2015
注:本题解参考代码均为 C++ 代码,如果你是 C 使用者,出现不认识的头文件时,若是 c
开头的,一般可以通过去掉开头的 c
然后在末尾添加 .h
来转换成 C 的头文件,如 cstdio
在 C 中为 stdio.h
,其他的请自行搜索。另外,如果出现不认识的写法,如 sort(排序)
、 stack(栈)
等,请自行实现。
签到题。逆序遍历一遍字符串,根据对应规则输出即可。
参考代码:
#include
#include
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;
}
典型的完全背包装满方案数的题,我们可以看做有 3 种物品,重量分别为 1, 2, 3,背包容量为钱数 N,装满背包的方案数就是此题的答案。
具体算法推荐学习这篇博客:背包问题——“01背包”及“完全背包”装满背包的方案总数分析及实现。
参考代码:
#include
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;
}
直接从 l 遍历 到 r,判断余数是否为 47 即可,注意负数取模的情况。
参考代码:
#include
#include
#include
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;
}
可以 DFS 一下,并利用回溯标记行列有没有用过,数量到 k 时记录答案。
参考代码:
#include
#include
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// 从当前行开始向下枚举行
for(int j=0; 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; iscanf("%s", graph[i]);
}
ans = 0;
DFS(0, 0);
printf("%d\n", ans);
}
return 0;
}
简单博弈,后手只需要跟着先手镜像取石子即可。
如果先手取完后剩余奇数个,则后手取对称位置的 1 个石子,否则后手取对称位置的 2 个石子,总能使先手必输。
只有当 n <= 2 先手可以一次取完时,先手才必胜。
参考代码:
#include
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;
}
多源最短路问题。把每个岛的字母编号映射成数字就可以和普通最短路一样处理了,注意可能有重边。
参考代码:
#include
#include
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; kfor(int i=0; ifor(int j=0; jif(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// 初始化
for(int j=0; j0;
}
scanf("%d", &n);
for(int i=0; iscanf("%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'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;
}
请参考这篇博客。
稍复杂的模拟题,按题意模拟即可。
参考代码:
#include
#include
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; jscanf("%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; jprintf("%s\n", a[j].name);
}
}
else {
sort(a, a+n, cmp1);
bool has_all_girl = false, found = false;
for(int j=0; jif(a[j].A) has_all_girl = true;
}
if(!has_all_girl) {
for(int j=m; jif(a[j].A) {
a[m] = a[j];
found = true;
break;
}
}
}
if(found) {
sort(a, a+m+1, cmp2);
for(int j=0; j1; ++j) {
printf("%s\n", a[j].name);
}
}
else {
sort(a, a+m, cmp2);
for(int j=0; jprintf("%s\n", a[j].name);
}
}
}
}
return 0;
}