2016年乐山师范学院程序设计大赛解题报告
来源:互联网 发布:淘宝爆款打造花钱 编辑:程序博客网 时间:2024/06/10 01:51
A:切割回文
先计算出所有子串是否是回文串,这个步骤的时间复杂度应该是O(N*N),然后再进行动态规划,当前的最少切割是有前面的最少切割所推导出来的,总的最坏时间复杂度是O(N *N)。
#include <stdio.h>#include <string.h>#define MAXN 1000#define MIN(a, b) (a < b ? a : b)int sub[MAXN][MAXN];void preprocess(char str[], int len) { int a, b, l, r; for (a = 0; a < MAXN; ++a) { for (b = 0; b < MAXN; ++b) { sub[a][b] = 0; } } for (a = 0; a < len; ++a) { l = a, r = a; while (0 <= l && r < len && str[l] == str[r]) { sub[l][r] = 1; l -= 1, r += 1; } l = a, r = a + 1; while (0 <= l && r < len && str[l] == str[r]) { sub[l][r] = 1; l -= 1, r += 1; } }}int main() { int T, dp[1000], len, a, b, c; char str[1001]; scanf("%d", &T); while (T--) { scanf("%s", str); len = strlen(str); preprocess(str, len); //for (a = 0; a < MAXN; ++a) dp[a] = 0; dp[0] = 1; for (a = 1; a < len; ++a) { dp[a] = dp[a - 1] + 1; for (b = a - 1; b >= 0; --b) { if (sub[b][a]) { if (b == 0) dp[a] = 1; else dp[a] = MIN(dp[a], dp[b - 1] + 1); } } } printf("%d\n", dp[len - 1] - 1); } return 0;}
B:特殊密码锁
每个按钮最多按一次,所以当前按钮的按或不按,只取决于当前按钮的状态和前一个按钮的状态,以此来进行下一步搜索,边缘情况特殊处理即可。可能我的状态表示方法略有欠妥,可自行斟酌。
#include <stdio.h>#include <string.h>#define INF 30#define MIN(a, b) (a < b ? a : b)char str[30], check[30];void change(int pos, int len) { if (pos == 0) { if (str[pos] == '1') str[pos] = '0'; else str[pos] = '1'; if (pos + 1 == len) return; if (str[pos + 1] == '1') str[pos + 1] = '0'; else str[pos + 1] = '1'; return; } if (str[pos - 1] == '1') str[pos - 1] = '0'; else str[pos - 1] = '1'; if (str[pos] == '1') str[pos] = '0'; else str[pos] = '1'; if (pos + 1 == len) return; if (str[pos + 1] == '1') str[pos + 1] = '0'; else str[pos + 1] = '1'; return;}int solve(int pos, int len, int step) { int res = INF, tmp; if (pos == len) { return str[pos - 1] == check[pos - 1] ? step : INF; } if (pos == 0) { tmp = solve(pos + 1, len, step); res = MIN(res, tmp); change(pos, len); tmp = solve(pos + 1, len, step + 1); res = MIN(res, tmp); change(pos, len); return res; } if (str[pos - 1] == check[pos - 1]) { tmp = solve(pos + 1, len, step); res = MIN(res, tmp); } else { change(pos, len); tmp = solve(pos + 1, len, step + 1); res = MIN(res, tmp); change(pos, len); } return res;}int main() { int res = INF, len; while (scanf("%s%s", str, check) != EOF) { len = strlen(str); if (len != strlen(check)) printf("impossible\n"); res = solve(0, len, 0); if (res == INF) printf("impossible\n"); else printf("%d\n", res); } return 0;}
C:最佳序列
目前有一个最坏时间复杂度为O(N*logN *logN)的思路,代码没有敲完,有兴趣讨论的朋友可以私信我。
D:字符串判等
先全部大写转小写,然后逐一去掉空格。
#include <stdio.h>#include <string.h>void to_lowercase(char *str) { int a, len = strlen(str); for (a = 0; a < len; ++a) { if (str[a] < 97 && str[a] != ' ') str[a] += 32; }}void remove_space(char *str) { int a, b = 0, len = strlen(str); for (a = 0; a < len; ++a) { if (str[a] != ' ') str[b++] = str[a]; } for (a = b; a < len; ++a) str[a] = 0;}int main() { char stra[10000], strb[10000]; int a, lena, lenb, res = 1; gets(stra), gets(strb); to_lowercase(stra), to_lowercase(strb); remove_space(stra), remove_space(strb); lena = strlen(stra), lenb = strlen(strb); if (lena != lenb) res = 0; //printf("%s\n%s\n", stra, strb); for (a = 0; a < (lena & lenb); ++a) { if (stra[a] != strb[a]) res = 0; } printf("%s\n", (res ? "YES" : "NO")); return 0;}
E:区间合并
先排序,再判断所有区间是否能连接起来。
但是介于数据范围,也可以用哈希解决此题。O(N * N)的最坏时间复杂度理论上是过不了的,但是最后确实有人这样做,然后拿到了Accepted,这就不科学了。
#include <stdio.h>typedef struct pair { int l, r;}pair;int compare(const void *a, const void *b) { return ((pair *)a)->l - ((pair *)b)->l;}int main() { int a, b, l, r, ok = 1, N; pair region[50000]; scanf("%d", &N); for (a = 0; a < N; ++a) { scanf("%d%d", ®ion[a].l, ®ion[a].r); } qsort(region, N, sizeof(pair), compare); l = region[0].l; r = region[0].r; for (a = 1; a < N; ++a) { if (r < region[a].l) { ok = 0; break; } r = r < region[a].r ? region[a].r : r; } if (ok) printf("%d %d\n", l, r); else printf("no\n"); return 0;}
F:字符环
这道题的重点在于环,本来应该是一道简单题目的,可能大多数同学都缺少这类型题目的处理经验吧。介于这题的数据范围很小,解决这道题目,只需将将每个串加倍,然后暴力去找到最长的公共子串即可。
#include <stdio.h>#include <string.h>#define MAX(a, b) a > b ? a : bint main() { char stra[10000], strb[10000]; int a, b, tmp, res = 0, lena, lenb; scanf("%s%s", stra, strb); lena = strlen(stra), lenb = strlen(strb); for (a = 0; a < lena; ++a) stra[a + lena] = stra[a]; for (a = 0; a < lenb; ++a) strb[a + lenb] = strb[a]; stra[lena * 2] = 0, strb[lenb * 2] = 0; //printf("%s\n%s\n", stra, strb); for (a = 0; a < lena * 2; ++a) { for (b = 0; b < lenb * 2; ++b) { tmp = 0; while (tmp + a < lena * 2 && tmp + b < lenb * 2 && stra[tmp + a] == strb[tmp + b] && tmp < lena && tmp < lenb) tmp += 1; res = MAX(res, tmp); } } printf("%d\n", res); return 0;}
G:分段函数
这场比赛,没有接触过程序设计竞赛的同学来讲,还是有很多道签到题,这题就是其中一道。
#include <stdio.h>int main() { double N, fN; scanf("%lf", &N); if (0 <= N && N < 5) fN = -N + 2.5; else if (5 <= N && N < 10) fN = 2 - 1.5 * (N - 3) * (N - 3); else if (10 <= N && N < 20) fN = N * 1.0 / 2 - 1.5; printf("%.3lf\n", fN); return 0;}
H:最小新整数
一个不足十位的数,没有0,删去K位。直接枚举出所有可能的数,找到一个最小的。枚举出所有的可能的数最多也就C(10,5)个,所以,应该只是考察代码能力吧。
#include <stdio.h>#include <string.h>#define MIN(a, b) (a < b ? a : b)#define INF 1e9int solve(char *number, int len, int n, int K) { int a, b; for (a = 0; a < len; ++a) { if (n >> a & 1) continue; K -= 1; } if (K) return INF; for (a = 0, b = 0; a < len; ++a) { if (n >> a & 1) { b = b * 10 + (number[a] - '0'); } } return b;}int main() { int T, K, len, res, a, b; char number[10]; scanf("%d", &T); while (T--) { scanf("%s%d", number, &K); len = strlen(number); res = INF; for (a = 0; a < 1 << len; ++a) { b = solve(number, len, a, K); res = MIN(res, b); } printf("%d\n", res); } return 0;}
I:健康生活每一天
签到题。
#include <stdio.h>int main() { int N, x, ok; double t; char flag[5]; scanf("%d", &N); while (N--) { scanf("%lf%d%s", &t, &x, flag); ok = 1; if (t < 7.0 || t > 8.0) ok = 0; if (x < 1500) ok = 0; if (flag[0] == 'N' && flag[1] == 'o') ok = 0; //printf("flag: %s\n", flag); printf(ok ? "Yes\n" : "No\n"); } return 0;}
J:3个数排序
签到题。
#include <stdio.h>void swap(int *a, int *b) { int t = *a; *a = *b; *b = t;}int main() { int a, b, c; scanf("%d%d%d", &a, &b, &c); if (a < b) swap(&a, &b); if (a < c) swap(&a, &c); if (b < c) swap(&b, &c); printf("%d %d %d\n", a, b, c); return 0;}
K:寻找配对数
先排序,然后两个循环枚举两个不同的数,再通过二分查找去判断集合中是否存在这个两个数的乘积,O(N *N *logN)的最坏时间复杂度就能拿到Accepted。注意爆int,注意去重。
#include <stdio.h>#define ll long longint compare(const void *a, const void *b) { return (int)((*(ll *)a) - (*(ll *)b));}int find(ll *arr, int len, ll val) { int l = 0, r = len, mid; while (l < r) { mid = l + (r - l) / 2; if (val == arr[mid]) return 1; if (val < arr[mid]) r = mid; else l = mid + 1; } return val == arr[l];}int main() { int N, res = 0; ll arr[1000]; int a, b, c; scanf("%d", &N); for (a = 0; a < N; ++a) scanf("%lld", arr + a); qsort(arr, N, sizeof(arr[0]), compare); for (a = 0; a < N; ++a) { for (b = a + 1; b < N; ++b) { if (arr[a] != 1 && find(arr, N, arr[a] * arr[b])) { res += 1; } } } printf("%d\n", res); return 0;}
L:组合数
这题有很多种不同的解法,主要在于自己怎么推导公式。
#include <stdio.h>#define ll long longint main() { int N, M; ll arr[21], a; for (arr[0] = arr[1] = 1, a = 2; a <= 20; ++a) { arr[a] = arr[a - 1] * a; } while (scanf("%d%d", &N, &M) != EOF) { if (N < M) { printf("0\n"); continue; } printf("%lld\n", arr[N] / arr[N - M] / arr[M]); } return 0;}
M:分解质因数
知道有的同学肯定会先筛选素数,但是如果仔细想想,确实是没有必要啊。
#include <stdio.h>int main() { int N, a; scanf("%d", &N); printf("%d=", N); for (a = 2; a <= N; ++a) { while (N % a == 0) { printf("%d", a); if ((N /= a) != 1) printf("*"); } } printf("\n"); return 0;}
- 2016年乐山师范学院程序设计大赛解题报告
- 2017年乐山师范学院程序设计大赛解题报告
- 2012年BNU新生程序设计大赛解题报告【非官方版】
- 乐师2017年新生程序设计大赛解题报告
- 2013年4月_武科大程序设计大赛_解题报告(problem 1001)
- 2013年4月_武科大程序设计大赛_解题报告(problem 1002)
- 2013年4月_武科大程序设计大赛_解题报告(problem 1003)
- 2013年4月_武科大程序设计大赛_解题报告(problem 1004)
- 2013年4月_武科大程序设计大赛_解题报告(problem 1005)
- 2013年4月_武科大程序设计大赛_解题报告(problem 1006)
- 2013年4月_武科大程序设计大赛(复赛)_解题报告(problem 1001)
- 2013年4月_武科大程序设计大赛(复赛)_解题报告(problem 1002)
- 2013年4月_武科大程序设计大赛(复赛)_解题报告(problem 1003)
- 2013年4月_武科大程序设计大赛(复赛)_解题报告(problem 1004)
- 2013年4月_武科大程序设计大赛(复赛)_解题报告(problem 1005)
- 2013年4月_武科大程序设计大赛(复赛)_解题报告(problem 1006)
- 【中北大学2013年第一学期新生程序设计大赛 解题报告】
- 华侨大学第三届程序设计大赛基础组决赛解题报告
- Sports
- 区间DP_Halloween Costumes_light oj_1422
- Java开发中的23种设计模式详解
- c++ socket 数据传输总结
- C++算法之最短路径
- 2016年乐山师范学院程序设计大赛解题报告
- Android核心基础(ListView)
- Java Primitive
- YZOJ 1572 [省队训练]calc
- FZU - 1928 硬币翻转游戏(2维nim游戏)
- 【2016年12月2日】百度网盘 IDM下载插件完美图文教程 完美解决开发者警告问题
- Java GUI编程设计
- Unity+ Photon服务器实时对战游戏——Photon服务器介绍(二)
- malloc实现原理