Problem A -> I
source
uva11877 -> 11885
solution
这些题都很挺简单的, 我们队1个半小时就把前6个题过了.
做法上, D模拟就可以了, 但我觉得有点小蛋疼, 我的想法是竖直或水平的情况特判, 其余情况按方向向量在四个方向讨论, 训练的时候这个题并不是我写的.
F题直接dfs, 加上一个剪支, 因为路径会把原图分成多个连通块, 所以每次找出当前连通块内所有数, 假设它们可以任意排列, 然后和已经搜到的串拼起来, 如果不比当前答案优, 那么就没必要继续搜下去.
I题不会推, 但是打个表很容易就找到规律了, 貌似我们队在这方面比较迟钝, 好几次打表都没太反应过来.
Problem J - Infinite Dictionaries
source
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=226&page=show_problem&problem=3008
solution
这真是个蛋疼题, 训练的时候我傻逼了, 以为reference是可以传递的, 实际上题目中的赋值指的就是指针赋值, 就和java的赋值一样.
这个题的难度就在实现上, 我的想法大概是这样的.
首先INTEGER和STRING可以看成同一种类型, 我都当作了std::string, 这里有个trick是整数可能为负, 我没有判断负号, RE了很多次.
做了这样的转换以后, 数据类型就只有std::string和dict两种了.
由于dict里面有很多pair, pair的第一个类型一定是std::string, 但是第二个就不一定了.
为了处理这种情况, 我把std::string和dict打包成了一个struct Complex, 里面有int data_type, std::string string, std::map <std::string, Complex*> dict;
data_type表示这个Complex是那种数据, string和dict就分别用于记录, 这样虽然会有一点内存的浪费, 但是实现dict就很容易了, 直接上std::map.
然后对于length操作, 直接返回std::map的size就可以了, 对于test, 实际上各个dict之间构成了一个有向图, 判断这个有向图有没有环就可以了(包括自环), 把tarjan求强连同分量的算法稍微修改一下即可.
对于assign操作, 我写了两个函数, parse_reference, 这个函数返回对Complex*的引用, 等号左边的部分调用这个函数就可以了, 等号右边的部分调用parse, 这个函数集成了需要new一个dict, new一个string和parse_reference三种情况, 返回的是Complex*.
对于parse_reference, 为了方便, 因为直接的变量只有26个, 所以我开了个全局变量Complex* ptr[26];
想清楚以后剩下的工作就很简单了.
一个可能的trick是[]操作可以取到一个原来没有的pair, 需要自己new出来.
#include <cstdio>
#include <algorithm>
#include <string>
#include <cassert>
#include <cctype>
#include <cstring>
#include <vector>
#include <set>
#include <map>
struct Complex;
typedef Complex* ComplexPointer;
int total_nodes;
struct Complex {
static const int STRING = 0;
static const int DICT = 1;
int data_type, id;
std::string string;
std::map <std::string, ComplexPointer> dict;
Complex() {
data_type = DICT;
id = total_nodes++;
}
Complex(const std::string& s) {
data_type = STRING;
string = s;
id = total_nodes++;
}
int length() const {
return (int)dict.size();
}
ComplexPointer& operator[](const std::string& s) {
if (!dict.count(s)) {
dict[s] = new Complex;
}
return dict[s];
}
void add_pair(const std::string& first, const ComplexPointer& second) {
dict[first] = second;
}
};
inline int id(char x) {
return x - 'a';
}
const int MAX_LENGTH = 333;
char buf[MAX_LENGTH];
ComplexPointer ptr[26];
ComplexPointer new_dict(int s, int t) {
#define CLR() (state = 0, first = second = "")
static std::vector <std::string> que_str;
static std::vector <ComplexPointer> que_ptr;
std::string first, second;
int state = 0;
que_str.clear();
que_ptr.clear();
for (; s < t; s++) {
if (buf[s] == '{') {
que_str.push_back(first);
que_ptr.push_back(new Complex);
CLR();
} else if (buf[s] == '}') {
if (state == 1) {
que_ptr.back()->add_pair(first, new Complex(second));
CLR();
}
ComplexPointer ptr = que_ptr.back();
que_ptr.pop_back();
if (que_ptr.empty()) {
return ptr;
}
que_ptr.back()->add_pair(que_str.back(), ptr);
que_str.pop_back();
} else if (buf[s] == ',') {
if (state == 1) {
que_ptr.back()->add_pair(first, new Complex(second));
CLR();
}
} else if (buf[s] == ':') {
state = 1;
} else {
state == 0 ? first += buf[s] : second += buf[s];
}
}
return que_ptr.front();
}
ComplexPointer& parse_reference(int s, int t) {
if (s + 1 == t) {
return ptr[id(buf[s])];
}
ComplexPointer now = ptr[id(buf[s++])];
while (s < t) {
int l = s + 1, r = s + 1;
for (; buf[r] != ']'; r++);
if (r + 1 == t) {
return (*now)[std::string(buf + l, buf + r)];
} else {
now = (*now)[std::string(buf + l, buf + r)];
s = r + 1;
}
}
}
ComplexPointer parse(int s, int t) {
if (buf[s] == '{') {
return new_dict(s, t);
} else if (buf[s] == '\'' || isdigit(buf[s]) || buf[s] == '-') {
return new Complex(std::string(buf + s, buf + t));
} else {
return parse_reference(s, t);
}
}
std::set <int> visited, stack;
bool dfs(ComplexPointer ptr) {
visited.insert(ptr->id);
stack.insert(ptr->id);
for (__typeof(ptr->dict.begin()) itr = ptr->dict.begin(); itr != ptr->dict.end(); itr++) {
if (!visited.count(itr->second->id) && dfs(itr->second)) {
return true;
} else if (stack.count(itr->second->id)) {
return true;
}
}
stack.erase(ptr->id);
return false;
}
int test(ComplexPointer ptr) {
visited.clear();
stack.clear();
return dfs(ptr);
}
int main() {
for (int i = 0; i < 26; i++) {
ptr[i] = new Complex;
}
while (gets(buf)) {
int l = strlen(buf), m = 0;
for (int i = 0; i < l; i++) {
if (buf[i] != ' ') {
buf[m++] = buf[i];
}
}
l = m;
if (l >= 4 && std::string(buf, buf + 4) == "test" ) {
printf("%d\n", test(parse(5, l - 1)));
} else if (l >= 6 && std::string(buf, buf + 6) == "length") {
printf("%d\n", parse(7, l - 1)->length());
} else {
for (int i = 0; i < l; i++) {
if (buf[i] == '=') {
parse_reference(0, i) = parse(i + 1, l);
break;
}
}
}
}
}
Problem K - Tetrahedrons and Spheres
source
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=226&page=show_problem&problem=3009
solution
开场的时候随便看了一下题, 瞥到了"Special Thanks: Jingbo Shang", 后来队友告诉我是个三维几何, 我就知道这个题要蛋疼了.
比赛的后三个小时我一直在做J, 因为refenrence理解错的原因一直蛋疼的RE, 队友一直在用simpson套simpson的方法做, 但是精度一直不够, 样例都过不了.
到现在我也没过这个题, std的做法倒是很简单, 一维simpson积分, 另一维梯形剖分. 我只能表示不会几何, 从来没写过梯形剖分, 这个题也只能暂时这样了, 后面学了梯形剖分再来过掉.