书上具体所有题目:http://pan.baidu.com/s/1hssH0KO
题目:算法竞赛入门经典 3-4/UVa455:Periodic Strings
代码:
//UVa455 #include<iostream> int main() { char str[82]; int num; std::cin >> num; while (num--) { std::cin>>str; char *ps = str; while (*++ps != '\0') { while (*ps != *str && *ps != '\0') ++ps; if (*ps == '\0') break;//循环长度即本身 char *begin = str, *end = ps; while (*++begin == *++end); if (*end == '\0'&&!((begin - str) % (ps - str))) break;//&&的后面的部分为了排除形如abcabcab的情况 } std::cout << ps - str << '\n'; if (num) std::cout << '\n'; } return 0; }分析:首先找到与输入的字符串的第一个字符相等的字符,然后判断是否循环,不是循环则继续找下一个与的哥字符相等的字符,直到读入'\0',则循环即本身而判断从第一个字符到此字符的前一个字符是否构成循环的办法是,此字符与首字符对应的下一个、下两个字符进行比较,直到遇到'\0',则说明有可能是相等的
如
abcdabcdabcdabcdabcdabcd
↑向右一个个比较
找到可能的循环点
↓向右一个个比较
abcdabcdabcdabcdabcdabcd
但此比较会漏掉如abcabcabcabcabcab的情况,最后一个ab导致整个字符串无循环,用!((begin - str) % (ps - str))来检查是不是循环了整数倍
题目:算法竞赛入门经典 3-5/UVa227:Puzzle
代码:(已更新为accept版本)
//UVa227 #include<iostream> using namespace std; int main() { //freopen("test.in", "r", stdin); //freopen("out.txt", "w", stdout); char puzzle[5][6]; int x, y, num = 0; char step; while (cin.getline(puzzle[0], 6) && puzzle[0][0] != 'Z') { if (num) cout << '\n'; bool flag = 0;//操作失败 for (int i = 1;i < 5;++i) cin.getline(puzzle[i], 6); for (x = 0;x < 5;++x) {//找出空格位置 for (y = 0;y < 5;++y) if (puzzle[x][y] == ' ') break; if (y != 5) break; } while ((cin >> step) && step != '0') { int cx = x, cy = y;//计算对应字母的坐标 switch (step) { case 'A':cx -= 1;break; case 'B':cx += 1;break; case 'L':cy -= 1;break; case 'R':cy += 1; } if (cx >= 0 && cx <= 4 && cy >= 0 && cy <= 4) {//替换字母和空格 puzzle[x][y] = puzzle[cx][cy]; puzzle[x = cx][y = cy] = ' ';//同时x、y变化为新的地址 } else {//操作失败的情况 while ((cin >> step) && step != '0');//吸收非法步骤后面的所有步骤 flag = 1; break; } } cout << "Puzzle #" << ++num << ":\n"; if (flag) cout << "This puzzle has no final configuration.\n"; else { for (int i = 0;i < 5;++i) { cout << puzzle[i][0]; for (int j = 1;j < 5;++j) cout << ' ' << puzzle[i][j]; cout << '\n'; } } cin.getline(puzzle[0], 3);//吸收'\n' } return 0; }抱怨:查了N次没找到错误是什么,看了网上和同学许多人的代码,思路都差不多,自己做了N组数据来检测我的答案都正确,而且貌似不是输出格式的原因。拿到了一份别人已经通过了的代码,输出重定向到文件,比较我的输出和他的输出,甚至做了个程序来比较两个输出文件内容是不是一样,但就是一样。那么应该是特殊数据导致失败,然而是在想不出有什么特殊数据会让它错误的。。。大神求告知。
(更新:找同学给我看了一下,他也基本没改什么,但又上传了一遍,莫名其妙过了。。。虽然不知道之前哪里不对,但是上面的代码也更新为通过了的版本了)
他似乎就仅仅是把本来的
switch (step) { case 'A':cx -= 1;break; case 'B':cx += 1;break; case 'L':cy -= 1;break; case 'R':cy += 1;break; default:cerr<<"Error:1\n";exit(0); }改成了现在的代码。好像就改了这个(之前由于没有通过,我也自己改了一小些的,改的都是些貌似无关紧要的东西,所以至今不知道是什么原因导致了之前的WA。。。。不爽)分析:注意个吸收cin后末尾的'\n'就行。还有吸收错误步骤后的所有步骤。本来很简单的题目,第一天莫名死活wrong answer不过,第二天莫名其妙又过了。。
题目:算法竞赛入门经典 3-6/UVa232:Crossword Answers
代码:
//UVa232 #include<iostream> #include<iomanip> using namespace std; int main() { char puzzle[10][10]; int num = 0; int px, py;//puzzle的长宽高 while ((cin >> px) && px != 0) { if (num) cout << '\n'; cin >> py; for (int i = 0;i < px;++i) for (int j = 0;j < py;++j) cin >> puzzle[i][j]; cout << "puzzle #" << ++num << ":\nAcross"; int number = 0; for (int i = 0;i < px;++i) for (int j = 0;j < py;++j) if (puzzle[i][j] != '*' && (i == 0 || j == 0 || puzzle[i - 1][j] == '*' || puzzle[i][j - 1] == '*')) {//找出起始格 ++number; if (j == 0 || puzzle[i][j - 1] == '*') {//输出 int jj = j; cout << '\n' << setw(3) << number << '.' << puzzle[i][jj++]; while (jj < py&&puzzle[i][jj] != '*') cout << puzzle[i][jj++]; } } number = 0; cout << "\nDown"; //down与找across的步骤类似,由于分开输出,就分开循环,总感觉效率上、代码重复率上欠妥 for (int i = 0;i < px;++i) for (int j = 0;j < py;++j) if (puzzle[i][j] != '*' && (i == 0 || j == 0 || puzzle[i - 1][j] == '*' || puzzle[i][j - 1] == '*')) { ++number; if (i == 0 || puzzle[i - 1][j] == '*') { int ii = i; cout << '\n' << setw(3) << number << '.' << puzzle[ii++][j]; while (ii < px&&puzzle[ii][j] != '*') cout << puzzle[ii++][j]; } } cout << '\n'; } return 0; } 分析:如中间注释所示,感觉我这样分开来算横里竖里的结果有点麻烦了,代码也重复性大。但是由于它要求Across与Down分开输入,所以就这样了。本来我还想①把across直接输出,down的先存到字符串里去,最后一口气输出来,还想着或者②定义一个[10][10]的int数组,第一遍across循环时找出所有eligible,第二遍输出down就快了。
现在想想还是①比较快,但是当时比较懒,没有改。
转载于:https://www.cnblogs.com/xienaoban/p/6798114.html
相关资源:算法竞赛入门经典第2版完整pdf