算法入门经典2 第3章解题报告
来源:互联网 发布:贵州云博大数据 编辑:程序博客网 时间:2024/05/17 04:58
【写在前面】 就不写题意了,紫书上面有中文翻译,下面水题我直接给出代码了,一些需要推导的详细写一下!
【3-1】水题,顺序扫描一遍就行了。复杂度O(len)
char s[82];bool vis[82];int main(){ int T; scanf("%d",&T); REP(i, T){ memset(vis, false, sizeof(vis)); scanf("%s", s); int ans = 0; int len = strlen(s); REP(i, len){ if(vis[i] || s[i] == 'X') continue; int cnt = 0; while(s[i] == 'O'){ vis[i] = true; cnt++, i++; } ans += cnt * (cnt + 1) / 2; } printf("%d\n", ans); } return 0;}
【3-2】同水题,模拟一下即可。复杂度O(len)
map<char, double> mp;char s[20];int main(){ mp['C'] = 12.01, mp['H'] = 1.008, mp['O'] = 16.00, mp['N'] = 14.01; int T; scanf("%d", &T); REP(j, T) { scanf("%s", s); int len = strlen(s); double ans = 0; REP(i, len){ if(isdigit(s[i])) continue; if(isdigit(s[i+1])){ double cnt = s[i+1] - '0'; int j = i + 2; while(isdigit(s[j])){ cnt = cnt * 10 + s[j] - '0'; j++; } ans += cnt * mp[s[i]]; } else{ ans += mp[s[i]]; } } printf("%.3f\n", ans ); } return 0;}
【3-3】把所有的数字放到数组里面,或者边循环边基数都可以。
int a[100010];int b[10];int main(){ int T, n; scanf("%d", &T); REP(k, T){ int cnt = 0; scanf("%d", &n); memset(b, 0, sizeof(b)); for(int i = 1; i <= n; i++){ int j = i; while(j){ a[cnt++] = j % 10; j /= 10; } } for(int i = 0; i < cnt; i++){ b[a[i]]++; } for(int i = 0; i < 9; i++){ printf("%d ", b[i]); } printf("%d\n", b[9]); } return 0;}
【3-4】模拟长度并判断,复杂度O(n^2)
char s[82];int main(){ int T; scanf("%d",&T); while(T--){ scanf("%s", s); int len = strlen(s); int ans; for(int i = 1; i <= len; i++){ bool ok = 1; string temp = ""; for(int j = 0; j < i; j++) temp += s[j]; for(int j = i; j < len; j += i){ string xx = ""; for(int k = j; k < i + j; k++){ xx += s[k]; } if(xx != temp){ ok = 0; break; } } if(ok){ ans = i; break; } } if(T >= 1) printf("%d\n\n", ans); else{ printf("%d\n",ans); } } return 0;}
【3-5】纯模拟,没啥说的!
char maze[5][5];char ope[1010];bool judge(int x, int y){ if(x >= 0 && x < 5 && y >= 0 && y < 5) return true; else return false;}int main(){ int ks = 0; while(gets(maze[0])){ if(maze[0][0] == 'Z') break; gets(maze[1]); gets(maze[2]); gets(maze[3]); gets(maze[4]); for(int i = 0; i < 5; i++){ if(maze[i][4] == '\0'){ maze[i][4] = ' '; } } int cnt = 0; while(~scanf("%c", &ope[cnt])){ if(ope[cnt] != '0') cnt++; else break; } ope[cnt++] = '0'; getchar(); int sx, sy; for(int i = 0; i < 5; i++){ for(int j = 0; j < 5; j++){ if(maze[i][j] == ' '){ sx = i, sy = j; } } } bool ok = 1; int len = strlen(ope); REP(i, len){ if(ope[i] == '0') break; if(ope[i] == 'L'){ if(judge(sx, sy - 1)){ maze[sx][sy] = maze[sx][sy-1]; maze[sx][sy-1] = ' '; sy--; } else{ ok = 0; break; } } if(ope[i] == 'R'){ if(judge(sx, sy + 1)){ maze[sx][sy] = maze[sx][sy+1]; maze[sx][sy+1]=' '; sy++; } else{ ok = 0; break; } } if(ope[i] == 'A'){ if(judge(sx-1, sy)){ maze[sx][sy] = maze[sx-1][sy]; maze[sx-1][sy] = ' '; sx--; } else{ ok = 0; break; } } if(ope[i] == 'B'){ if(judge(sx+1, sy)){ maze[sx][sy] = maze[sx+1][sy]; maze[sx+1][sy] = ' '; sx++; } else{ ok = 0; break; } } } if(ks++) printf("\n"); printf("Puzzle #%d:\n", ks); if(ok == 0){ printf("This puzzle has no final configuration.\n"); } else{ for(int i = 0; i < 5; i++){ for(int j = 0; j < 4; j++){ printf("%c ",maze[i][j]); } printf("%c\n",maze[i][4]); } } } return 0;}
【3-6】纯模拟,不过输出要按照序号排序之后再输出。格式有点坑,pe了很多发。
int n, m;char maze[12][12];int id[12][12];bool check(int x, int y){ if(x >= 0 && x < n && y >= 0 && y < m){ return true; } else{ return false; }}struct node{ int pos; string s; bool operator<(const node &rhs) const{ return pos < rhs.pos; } void init(){ pos = 0; s = ""; }}ans[110];int main(){ int ks = 1; while(scanf("%d", &n), n) { scanf("%d", &m); for(int i = 0; i < n; i++){ scanf("%s", maze[i]); } for(int i = 0; i < 110; i++){ ans[i].init(); } int cntt = 0; memset(id, 0, sizeof(id)); int cnt = 0; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ if(maze[i][j] == '*') continue; if((check(i-1, j) == false || maze[i-1][j] == '*') || (check(i, j-1) == false || maze[i][j-1] == '*')){ id[i][j] = ++cnt; } } } if(ks>1) printf("\n"); printf("puzzle #%d:\n", ks++); printf("Across\n"); int k; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j += k){ if(id[i][j] != 0){ //printf(" %d.", id[i][j]); ans[cntt].pos = id[i][j]; k = 0; while( maze[i][j+k] != '*' && (j + k) < m){ //printf("%c", maze[i][j+k]); ans[cntt].s += maze[i][j+k]; k++; } //printf("\n"); cntt++; } else{ k = 1; } } } sort(ans, ans+cntt); for(int i = 0; i < cntt; i++){ printf("%3d.",ans[i].pos); cout<<ans[i].s<<endl; } cntt = 0; for(int i = 0; i < 110; i++){ ans[i].init(); } printf("Down\n"); for(int i = 0; i < m; i++){ for(int j = 0; j < n; j += k){ if(id[j][i] != 0){ //printf(" %d.", id[j][i]); ans[cntt].pos = id[j][i]; k = 0; while(maze[j+k][i] != '*' && (j + k) < n){ //printf("%c", maze[j+k][i]); ans[cntt].s += maze[j+k][i]; k++; } cntt++; //printf("\n"); } else{ k = 1; } } } sort(ans, ans+cntt); for(int i = 0; i < cntt; i++){ printf("%3d.",ans[i].pos); cout<<ans[i].s<<endl; } } return 0;}
【3-7】贪心,找每一列出现最多的那个字母!复杂度O(n*m)
char s[1002];struct node{ int a, c, g, t; void init(){ a = 0, c = 0, g = 0, t = 0; }}thing[1005];int main(){ int T, n, m; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i = 0; i < m; i++){ thing[i].init(); } for(int i = 0; i < n; i++){ scanf("%s", s); for(int j = 0; j < m; j++){ if(s[j] == 'A') thing[j].a++; else if(s[j] == 'C') thing[j].c++; else if(s[j] == 'G') thing[j].g++; else thing[j].t++; } } char ans[1005] = {'0'}; int maxx, anss = 0; for(int i = 0; i < m; i++){ ans[i] = 'A'; maxx = thing[i].a; if(thing[i].c > maxx){ ans[i] = 'C'; maxx = thing[i].c; } if(thing[i].g > maxx){ ans[i] = 'G'; maxx = thing[i].g; } if(thing[i].t > maxx) { ans[i] = 'T'; maxx = thing[i].t; } anss += n - maxx; } ans[m] = '\0'; printf("%s\n", ans); printf("%d\n", anss); } return 0;}
【3-8】计算循环节。n除以m的余数只能是0~m-1,根据抽屉原则,当计算m+1次时至少存在一个余数相同, 即为循环节;存储余数和除数,输出即可。复杂度O(m)
int a[3003], b[3003], c[3003];int main(){ int n, m, t; while(scanf("%d%d", &n, &m) != EOF) { t = n; memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); memset(c, 0, sizeof(c)); int cnt = 0; a[cnt++] = n/m; n = n % m; while(!b[n] && n){ b[n] = cnt; //记录第一次出现的位置 c[cnt] = n; a[cnt++] = 10*n/m; n = 10*n%m; } printf("%d/%d = %d.", t, m, a[0]); for(int i = 1; i < cnt && i <= 50; i++){ if(n && c[i] == n) printf("("); printf("%d", a[i]); } if(n == 0) printf("(0"); if(cnt > 50) printf("..."); printf(")\n"); printf(" %d = number of digits in repeating cycle\n\n", n == 0 ? 1 : cnt - b[n]); } return 0;}
【3-9】满足单调性,O(n扫描一下文本串即可!
char s1[100010], s2[100010];int main(){ while(scanf("%s%s", s1,s2) != EOF) { int len1 = strlen(s1); int len2 = strlen(s2); int p = 0; if(len1 > len2){ printf("No\n"); continue; } for(int i = 0; i < len2; i++){ if(s2[i] == s1[p]){ p++; } } if(p == len1){ printf("Yes\n"); } else{ printf("No\n"); } } return 0;}
【3-10】根据长方体的特点去判断即可!
struct Plane{ int x, y; bool operator<(const Plane &rhs) const{ if(x == rhs.x) return y > rhs.y; return x > rhs.x; }}p[6];bool judge(){ if(memcmp(p, p + 1, sizeof(Plane)) || memcmp(p + 2, p + 3, sizeof(Plane)) || memcmp(p + 4, p + 5, sizeof(Plane))) return false; if(p[0].x != p[2].x || p[0].y != p[4].x || p[2].y != p[4].y) return false; return true;}int main(){ while(scanf("%d%d",&p[0].x,&p[0].y) != EOF) { if(p[0].x < p[0].y) swap(p[0].x, p[0].y); for(int i = 1; i < 6; i++){ scanf("%d%d",&p[i].x,&p[i].y); if(p[i].x < p[i].y){ swap(p[i].x, p[i].y); } } sort(p, p + 6); if(judge()){ printf("POSSIBLE\n"); } else{ printf("IMPOSSIBLE\n"); } } return 0;}
【3-11】固定一个不变,移动宁一个,判断合法性,取最小值 复杂度O(max(len1, len2))
char s1[200], s2[200];int len1, len2;int solve(char *s1, char *s2, int n){ int sumlen = len1 + len2; int minn = min(len1, len2); int len = sumlen; REP(i, n){ int ok = 1, lcm = min(n - i, minn); REP(j, lcm){ if(s1[i + j] == '2' && s2[j] == '2'){ ok = 0; break; } } if(ok && len > sumlen - lcm){ len = sumlen - lcm; } } return len;}int main(){ while(scanf("%s%s",s1,s2)!=EOF) { len1 = strlen(s1); len2 = strlen(s2); int ans = min(solve(s1, s2, len1), solve(s2, s1, len2)); printf("%d\n", ans); } return 0;}
【3-12】
如果每组数都要计算比较找到对应的m和e运算量太大,所以先打表,涉及浮点数表示的一些数学知识。 假设当前一层M和E的值为m和e,它们的位数分别为i和j。 首先计算m的值,用二进制表示的话,m的值为0.11…,也就是m = 2^(-1) + 2^(-2) + … + 2^(-1 - i)(i比实际1的个数少1个),也就是m = 1 - 2^(-1 - i)。 接下来就是计算e的值,不难得出,e = 2^j - 1。 那么也就有m * 2^e = A * 10^B,似乎可以直接计算了。然而,直接这样算的话是不行的,因为当e太大的话(e最大可以是1073741823,注意这还只是2的指数),等号左边的数就会超出上限,所以要想继续算下去,就得自己去想办法再写出满足要求的类来,这显然太麻烦了。所以,这个时候我们对等式两边同时取对数,这个时候就有 log10(m) + e × log10(2) = log10(A) + B。因为此时m和e的值都是确定的,所以不妨令等式左边为t,也就有t = log10(A) + B。 这个时候就有问题了,A和B怎么算。 科学记数法对于A,有1 ≤ A < 10。那么0 < log10(A) < 1。所以t的小数部分就是log10(A),整数部分就是B,即B = ⌊t⌋,A = 10^(t - B)。那么接下来,我们只需要开出两个二维数组来,分别记录对应i和j下A和B的大小,之后从输入里提取出A和B的大小,去二维数组里面查找对应的i和j即可。编程知识: 1.如果浮点数赋值给整数,小数部分会被截取。 2.类似这样5.699141892149156e76的数据串,想把e两端的数据分别赋给两个变量,可以先用string接收整个数据串,将string中的'e'替换为‘ ’,再将string拷贝到istringstream的一个对象,再从该对象读取到两个变量即可。
double A[20][40];long B[20][40];string s;void init(){ REP(m, 9){ REPZ(e, 30){ double x = 1 - pow(2, -1 - m), y = pow(2, e) - 1; double t = log10(x) + y*log10(2); B[m][e] = t; A[m][e] = pow(10, t - B[m][e]); } }}int main(){ init(); while(cin>>s){ if(s == "0e0") break; for(auto it = s.begin(); it != s.end(); it++){ if(*it == 'e'){ *it = ' '; break; } } istringstream is(s); double a; long b; bool ok = 0; is>>a>>b; REP(m, 9){ REPZ(e, 30){ if(b == B[m][e] && (fabs(a - A[m][e]) < 1e-5)){ cout<<m<<" "<<e<<endl; ok = 1; break; } } if(ok) break; } } return 0;}
0 0
- 算法入门经典2 第3章解题报告
- 算法入门经典2 第4章解题报告
- 算法入门经典2 第5章解题报告
- 算法竞赛入门经典(第一版) 第五章 解题报告
- 算法竞赛入门经典(第2版)-刘汝佳-第三章解题源码(C语言)
- 算法竞赛入门经典第3章
- 算法竞赛入门经典(第2版)-刘汝佳-第四章解题源码(C语言)(部分)
- 算法竞赛入门经典(第2版)-刘汝佳-第五章解题源码(C++语言)(部分)
- 算法竞赛入门经典(第2版)-刘汝佳-第六章解题源码(C++语言)(部分)
- 算法竞赛入门经典(第2版)-刘汝佳-第七章解题源码(C++语言)(部分)
- 算法竞赛入门经典(第2版)-刘汝佳-第八章例题解题源码(C++语言)(部分)
- 算法竞赛入门经典(第2版)-刘汝佳-第九、十一章例题解题源码(C++语言)(部分)
- 算法竞赛入门经典(第2版)-刘汝佳-解题源码说明
- (解题报告)入门经典2版———第三章习题1
- 算法竞赛入门经典(第2版)笔记--第3章
- 算法竞赛入门经典第3章【读书笔记】
- 算法竞赛入门经典第3章【小结与习题】
- 算法竞赛入门经典 第3章 习题答案
- Linux实现负载均衡
- 安全算法
- hudson安装以及使用
- 从零开始学写HTTP服务器(三)请求资源
- C++ const 用法总结
- 算法入门经典2 第3章解题报告
- 【Leetcode】477. Total Hamming Distance
- 求一个int数是否是4的幂
- python3 串口通讯
- MAC10.12Caps Lock失灵
- SpringMVC 菜鸟教程 3 文件上传 CommonsMultipartResolver
- 大话设计模式-工厂方法模式
- 滑膜控制的基本原理
- CSDN公式编辑