文章目录
UVa227 Puzzles
问题 ACM/ICPC World Finals 1993
代码&注释
/*
Dreams never shine!
It's you that shine while chasing your dreams :)
JAYO!!
*/
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <assert.h>
using namespace std;
struct Point {
int x, y;
Point(int x = 0, int y = 0): x(x), y(y) {}
};
typedef Point Vector;
Vector operator + (const Vector& A, const Vector& B) {
return Vector(A.x + B.x, A.y + B.y);
}
const int GSize = 5;
vector<string> grid;
Point ePos;
map<char, Vector> DIRS;
bool valid(const Point& p) {
return p.x >= 0 && p.x < GSize && p.y >=0 && p.y < GSize;
}
void printGrid() {
for (int i = 0; i < GSize; i++) {
for (int j = 0; j < GSize; j++) {
if (j) cout << ' ';
cout << grid[i][j];
}
cout << endl;
}
}
bool tryMove(char cmd) {
// cout << "move " << cmd << ":" <<endl;
if (!DIRS.count(cmd)) return false;
assert(DIRS.count(cmd)); // 为假, 抛异常
Point p = ePos + DIRS[cmd]; // 计算新空格的位置
// p.x = ePos.x + DIRS[cmd].x;
// p.y = ePos.y + DIRS[cmd].y;
if (!valid(p)) return false;
swap(grid[p.x][p.y], grid[ePos.x][ePos.y]); // 新空格处的值和原空格' ', 值交换
ePos = p; // 更新 空格
// printGrid();
return true;
}
int main()
{
int t = 1;
string line;
DIRS['A'] = Vector(-1, 0);
DIRS['B'] = Vector(1, 0);
DIRS['L'] = Vector(0, -1);
DIRS['R'] = Vector(0, 1);
while (true) {
grid.clear();
ePos.x = -1;
ePos.y = -1;
for (int i = 0; i < GSize; i++) {
getline(cin, line);
if (line == "Z") return 0;
assert(line.size() == GSize); // 为真,不抛异常
for (int j = 0; j < GSize; j++) { // 找到 空格, 定位给 ePos
if (line[j] == ' ') {
assert(ePos.x == -1 && ePos.y == -1); // 确保是初始化时的空格值
ePos.x = i;
ePos.y = j;
}
}
grid.push_back(line); // 一行一行储存记录
}
char move;
string moves;
while (true) { // 记录下操作指令(上下左右之类的操作)
getline(cin, line);
assert(!line.empty());
bool end = *(line.rbegin()) == '0'; // 判断是否输入结束值 0
if (!end) moves.append(line);
else moves.append(line, 0, line.size() - 1);
if (end) break;
}
bool legal = true;
for (int i = 0; i < moves.size(); i++) { // 开始执行指令
if (!tryMove(moves[i])) {
legal = false;
break;
}
}
if (t > 1) cout << endl;
cout << "Puzzle #" << t++ << ":" << endl;
if (legal) printGrid();
else cout << "This puzzle has no final configuration." << endl;
}
return 0;
}
UVA232 Crossword Answers
问题 ACM/ICPC World Finals 1994
代码&注释
/*
Dreams never shine!
It's you that shine while chasing your dreams :)
JAYO!!
*/
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
using namespace std;
struct Point {
int x, y;
Point(int x = 0, int y = 0): x(x), y(y) {}
};
typedef Point Vector;
Vector operator + (const Vector& A, const Vector& B) {
return Vector(A.x + B.x, A.y + B.y);
}
int R, C; // row, column
const int MAXC = 16;
char grid[MAXC][MAXC];
inline bool valid(const Point& p) {
return p.x >= 0 && p.x < R && p.y >= 0 && p.y < C;
}
int main()
{
char buf[MAXC];
int bufLen;
const Vector dLeft(0, -1), dUp(-1, 0), dRight(0, 1), dDown(1, 0);
for (int t = 1; scanf("%d%d", &R, &C) == 2 && R; t++) {
vector<Point> eligible;
vector<int> down, across;
if (t > 1) puts("");
printf("puzzle #%d:\n", t); // #define _for(i, a, b) for (int i = (a); i < (b); ++i)
_for(i, 0, R) {
scanf("%s", grid[i]);
_for(j, 0, C) {
if (grid[i][j] == '*') continue;
Point p(i, j), left = p + dLeft, up = p + dUp; // left 为左侧位置, up 为上
bool isCross = !valid(left) || grid[left.x][left.y] == '*'; // 判断是否能作为为across起点
bool isDown = !valid(up) || grid[up.x][up.y] == '*'; // 判断是否能作为为down起点
if (isCross) across.push_back(eligible.size()); // 记录across起点所对应的数字编号 + 1(即eligible的末尾)
if (isDown) down.push_back(eligible.size()); // 记录down起点所对应的数字编号 + 1(同上,该末尾即将插入p)
if (isCross || isDown) eligible.push_back(p); // 存储p(Point p)(存储到末尾)
}
}
puts("Across");
for (auto n : across) { // n对应eligible中储存的cross起始点p的下标
bufLen = 0;
memset(buf, 0, sizeof(buf));
Point p = eligible[n]; // 找到坐标(x, y)
while (valid(p) && grid[p.x][p.y] != '*') {
buf[bufLen++] = grid[p.x][p.y]; // 从grid中取得p对应的char值, 暂存在buff中
p = p + dRight;
}
printf("%3d.%s\n", n + 1, buf); // n是从0开始的
}
puts("Down");
for (auto n : down) {
bufLen = 0;
memset(buf, 0, sizeof(buf));
Point p = eligible[n];
while (valid(p) && grid[p.x][p.y] != '*') { // 确定down的重点(超出边界,遇到*, 终止)
buf[bufLen++] = grid[p.x][p.y];
p = p + dDown;
}
printf("%3d.%s\n", n + 1, buf);
}
}
return 0;
}
知识点
inline
在c/c++中,为了解决一些频繁调用的
小函数大量消耗栈空间(栈内存)的问题,
特别的引入了inline修饰符,表示为内联函数,
栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。
在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足
而导致程序出错的问题,
如,函数的死循环递归调用的最终结果就是导致栈内存空间枯竭。
增加了 inline 关键字的函数称为“内联函数”。
内联函数和普通函数的区别在于:当编译器处理调用内联函数的语句时,
不会将该语句编译成函数调用的指令,
而是直接将整个函数体的代码插人调用语句处,
就像整个函数体在调用处被重写了一遍一样。
puts()
出字符串时都使用 printf(),
通过“%s”输出字符串。
其实还有更简单的方法,就是使用 puts() 函数。
使用 puts() 函数连换行符 '\n' 都省了,
使用 puts() 显示字符串时,系统会自动在其后添加一个换行符
UVA-1368 DNA Consensus String
问题 ACM/ICPC Seoul 2006
代码&注释
/*
Dreams never shine!
It's you that shine while chasing your dreams :)
JAYO!!
*/
#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <algorithm>
using namespace std;
struct ChCnt {
int cnt; // 出现次数
char c; // 字符
void init(char ch = 'A') {
c = ch;
cnt = 0;
}
ChCnt() { init(); }
bool operator < (const ChCnt& cc2) const {
return cnt > cc2.cnt || (cnt == cc2.cnt && c < cc2.c);
}
};
int main()
{
int T = 1, m, n;
cin >> T;
string line;
vector<string> seqs;
char IDX[256] = {0};
IDX['A'] = 0;
IDX['C'] = 1;
IDX['G'] = 2;
IDX['T'] = 3;
while (T--) {
seqs.clear();
cin >> m >> n;
for (int i = 0; i < m; i++) { // 存储数据
cin >> line;
assert(line.size() == n);
seqs.push_back(line);
}
string ansStr;
int ans = 0;
vector<ChCnt> ccs(4);
for (int i = 0; i < n; i++) { // 一列一列的处理
ccs[0].init('A'); // 初始化(用来统计的变量)
ccs[1].init('C');
ccs[2].init('G');
ccs[3].init('T');
for (int j = 0; j < m; j++) { // 每一列逐行增加(进行统计)
ccs[IDX[seqs[j][i]]].cnt++;
}
sort(ccs.begin(), ccs.end()); // 先按照出现次数再按字符进行排序
ansStr += ccs.front().c; // 得到排序后的首字母, 拼接到作为答案的字符串中
ans += (m - ccs.front().cnt); // 得到得到每一列字符不同的行数
}
cout << ansStr << endl << ans << endl;
}
return 0;
}
小结论
刷题目记录下来!!!
记在小本子上!!!
算法竞赛入门经典
买了这么多天,你
入门了吗???
加油,专注,结合书籍,把书本上的系统学习吸收,反复巩固,多刷几遍!!!