├── .gitignore ├── arrayandstring ├── uva272.cpp ├── sikao2.cpp ├── uva10082.cpp ├── uva1585.cpp ├── uva1225.cpp ├── uva455.cpp ├── uva1586.cpp ├── uva1368.cpp ├── uva202.cpp ├── uva227.cpp ├── uva232-2.cpp └── uva232-1.cpp ├── ch5 ├── uva10763.cpp ├── uva136.cpp ├── uva10391.cpp ├── uva10935.cpp ├── uva10474.cpp ├── uva156.cpp ├── uva1594.cpp ├── uva1595.cpp ├── uva1593.cpp ├── uva10815.cpp ├── uva12100.cpp ├── uva540.cpp ├── uva400.cpp ├── uva1592-b.cpp ├── uva1592.cpp ├── uva12096.cpp ├── uva101.cpp └── uva230.cpp ├── ch6 ├── uva839.cpp ├── uva679-b.cpp ├── uva11988.cpp ├── uva679.cpp ├── uva11988-b.cpp ├── uva514.cpp ├── uva297-b.cpp ├── uva536.cpp ├── uva673.cpp ├── uva712.cpp ├── uva442.cpp ├── uva439.cpp ├── uva10305.cpp ├── uva699.cpp ├── uva572.cpp ├── uva548.cpp ├── uva1600-b.cpp ├── uva297.cpp ├── uva10129-b.cpp ├── uva12166.cpp ├── uva10526.cpp ├── uva1572.cpp ├── uva122.cpp ├── uva12657.cpp ├── uva804.cpp ├── uva1600.cpp ├── uva1103-b.cpp ├── uva10129.cpp ├── uva122-b.cpp ├── uva210-c.cpp ├── uva210.cpp ├── uva210-b.cpp ├── uva122-c.cpp ├── uva1599.cpp ├── uva1103-c.cpp ├── uva506.cpp ├── uva816-b.cpp ├── uva806.cpp ├── uva1103.cpp └── uva816.cpp ├── ch7 ├── uva11059.cpp ├── permut.cpp ├── uva10976.cpp ├── uva12325.cpp ├── uva725.cpp ├── uva524.cpp ├── uva1374.cpp ├── uva129.cpp ├── uva690.cpp ├── uva690-d.cpp ├── uva208.cpp ├── uva690-b.cpp ├── uva690-c.cpp ├── uva818.cpp ├── uva818-b.cpp ├── uva1343.cpp ├── uva140.cpp ├── uva1603.cpp ├── uva10603.cpp ├── uva11212.cpp ├── uva1603-b.cpp ├── uva211.cpp ├── uva1602.cpp ├── uva1354.cpp ├── uva225-c.cpp ├── uva225.cpp ├── uva225-b.cpp ├── uva1601.cpp └── uva1601-b.cpp ├── ch4 ├── uva1339.cpp ├── uva133.cpp ├── uva489.cpp ├── uva213.cpp ├── uva201-2.cpp ├── uva201.cpp ├── uva220.cpp └── uva1589.cpp ├── ch8 └── uva120.cpp └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.vscode 3 | *.in 4 | *.out -------------------------------------------------------------------------------- /arrayandstring/uva272.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | int c, q = 1; 7 | while(~(c = getchar())) { 8 | if(c == '"') printf("%s", q ? "``" : "''"), q = !q; 9 | else printf("%c", c); 10 | } 11 | return 0; 12 | } -------------------------------------------------------------------------------- /arrayandstring/sikao2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define maxn 10000000 + 10 4 | 5 | char s[maxn]; 6 | 7 | int main() { 8 | scanf("%s", s); 9 | int tot = 0; 10 | for(int i = 0; i < strlen(s); i++) 11 | if(s[i] == '1') tot++; 12 | printf("%d\n", tot); 13 | return 0; 14 | } -------------------------------------------------------------------------------- /arrayandstring/uva10082.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | char s[] = "`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./"; 6 | 7 | int main() { 8 | int c; 9 | while(~(c = getchar())) { 10 | int i; 11 | for(i = 0; s[i] && s[i] != c; i++); 12 | if(s[i]) putchar(s[i - 1]); 13 | else putchar(c); 14 | } 15 | return 0; 16 | } -------------------------------------------------------------------------------- /arrayandstring/uva1585.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const int N = 100; 4 | char s[N]; 5 | 6 | int main(void) { 7 | int T; 8 | scanf("%d", &T); 9 | while(T--) { 10 | scanf("%s", &s); 11 | int cur = 0; 12 | int tot = 0; 13 | for(int i = 0; s[i]; i++) { 14 | if(s[i] == 'O') tot += ++cur; 15 | else cur = 0; 16 | } 17 | printf("%d\n", tot); 18 | } 19 | return 0; 20 | } -------------------------------------------------------------------------------- /ch5/uva10763.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | typedef pair pii; 6 | 7 | map cntmap; 8 | int n; 9 | 10 | void solve() { 11 | for(int i = 0; i < n; i++) { 12 | int a, b; scanf("%d%d", &a, &b); 13 | cntmap[b]++, cntmap[a]--; 14 | } 15 | for(auto& t : cntmap) 16 | if(t.second != 0) {puts("NO"); return;} 17 | puts("YES"); 18 | } 19 | 20 | int main(void) { 21 | while(scanf("%d", &n), n) 22 | cntmap.clear(), solve(); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /ch6/uva839.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int solve() { 6 | int w1, d1, w2, d2; 7 | scanf("%d%d%d%d", &w1, &d1, &w2, &d2); 8 | if(!w1) w1 = solve(); 9 | if(!w2) w2 = solve(); 10 | if(w1 == -1 || w2 == -1) return -1; 11 | if(w1 * d1 == w2 * d2) return w1 + w2; 12 | else return -1; 13 | } 14 | 15 | int main(void) { 16 | int n; scanf("%d", &n); 17 | while(n--) { 18 | if(solve() != -1) puts("YES"); 19 | else puts("NO"); 20 | if(n) puts(""); 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /arrayandstring/uva1225.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int N = 10; 5 | int ans[N]; 6 | 7 | void solve(int n) { 8 | while(n) { 9 | ans[n % 10]++; 10 | n /= 10; 11 | } 12 | } 13 | 14 | int main () { 15 | int T; 16 | scanf("%d", &T); 17 | while(T--) { 18 | int n; scanf("%d", &n); 19 | memset(ans, 0, sizeof ans); 20 | for(int i = 1; i <= n; i++) { 21 | solve(i); 22 | } 23 | for(int i = 0; i < N; i++) 24 | printf(i < N - 1 ? "%d " : "%d\n", ans[i]); 25 | } 26 | return 0; 27 | } -------------------------------------------------------------------------------- /ch6/uva679-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | // 方向,取决于是第几个进入该子树的小球 6 | // 奇数次则向左,偶数次则向右 7 | // 第一层:奇数向左,偶数向右 8 | // 第二层:进入第一层的x个球中,有x/2+1个向左进入第二层,有x/2个向又进入第二层, 9 | // 根据新计算出的序数,计算出从哪个方向进入第三层,以此类推。。。 10 | int main(void) { 11 | int T; scanf("%d", &T); 12 | int d, x; 13 | while(T--) { 14 | int x; 15 | scanf("%d%d", &d, &x); 16 | int t = 1; 17 | for(int i = 1; i < d; i++) { 18 | if(x & 1) t *= 2, x = x / 2 + 1; 19 | else t = t * 2 + 1, x /= 2; 20 | } 21 | printf("%d\n", t); 22 | } 23 | return 0; 24 | } -------------------------------------------------------------------------------- /ch6/uva11988.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main(void) { 7 | string str; 8 | while(cin >> str) { 9 | list list; 10 | bool tail = true; 11 | auto itr = list.end(); 12 | for(int i = 0; i < str.size(); i++) { 13 | char ch = str[i]; 14 | if(ch == '[') itr = list.begin(); 15 | else if(ch == ']') itr = list.end(); 16 | else list.insert(itr, ch); 17 | } 18 | for(auto& ch : list) { 19 | putchar(ch); 20 | } 21 | puts(""); 22 | } 23 | return 0; 24 | } -------------------------------------------------------------------------------- /arrayandstring/uva455.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | bool verify(string& s, int p) { 6 | int n = s.size(); 7 | if(n % p) return false; 8 | for(int i = 0; i < n; i += p) 9 | if(s.substr(0, p) != s.substr(i, p)) return false; 10 | return true; 11 | } 12 | 13 | void solve() { 14 | string s; cin >> s; 15 | for(int i = 1; i <= s.length(); i++) 16 | if(verify(s, i)) { 17 | printf("%d\n", i); 18 | break; 19 | } 20 | } 21 | 22 | int main() { 23 | int n; scanf("%d", &n); 24 | while(n--) { 25 | solve(); 26 | if(n) puts(""); 27 | } 28 | return 0; 29 | } -------------------------------------------------------------------------------- /ch5/uva136.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef long long ll; 6 | 7 | using namespace std; 8 | 9 | int main(void) { 10 | priority_queue, greater> pq; 11 | unordered_set set; 12 | pq.push(1); 13 | set.insert(1); 14 | for(int cnt = 0; cnt < 1499; cnt++) { 15 | ll t = pq.top(); pq.pop(); 16 | int a[] = {2, 3, 5}; 17 | for(int i = 0; i < 3; i++) { 18 | ll val = t * a[i]; 19 | if(!set.count(val)) set.insert(val), pq.push(val); 20 | } 21 | } 22 | printf("The 1500'th ugly number is %d.\n", pq.top()); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /ch5/uva10391.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | // 很显然这题只能枚举了,但是枚举的方法有2种 9 | // 1. 将字典中的词,全部22组合,时间复杂度达到了1e10,爆定了 10 | // 2. 枚举全部词,对每个词进行分割,然后查询分割后的2部分是否都在字典中,最坏情况下,如果每个字符串长度都是 11 | // 1e5,时间复杂度才会达到1e10 12 | int main(void) { 13 | vector v; 14 | unordered_set set; 15 | string t; 16 | while(cin >> t) v.push_back(t), set.insert(t); 17 | for(auto& s : v) { 18 | for(int i = 0; i < s.size(); i++) 19 | if(set.count(s.substr(0, i)) && set.count(s.substr(i))) { 20 | puts(s.c_str()); break; 21 | } 22 | } 23 | return 0; 24 | } -------------------------------------------------------------------------------- /ch5/uva10935.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void solve(int n) { 7 | deque dq; 8 | vector dis; 9 | for(int i = 1; i <= n; i++) dq.push_back(i); 10 | while(dq.size() > 1) 11 | dis.push_back(dq.front()), dq.pop_front(), dq.push_back(dq.front()), dq.pop_front(); 12 | printf("Discarded cards:"); 13 | for(int i = 0; i < n - 1; i++) { 14 | if(i > 0) putchar(','); 15 | printf(" %d", dis[i]); 16 | } 17 | printf("\n"); 18 | printf("Remaining card: %d\n", dq.front()); 19 | } 20 | 21 | int main(void) { 22 | int n; 23 | while(cin >> n, n) { 24 | solve(n); 25 | } 26 | return 0; 27 | } -------------------------------------------------------------------------------- /ch5/uva10474.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | 8 | int main(void) { 9 | int n, q; 10 | for(int cnt = 1; cin >> n >> q && n; cnt++) { 11 | vector v; 12 | for(int i = 0, t; i < n; i++) 13 | cin >> t, v.push_back(t); 14 | sort(v.begin(), v.end()); 15 | printf("CASE# %d:\n", cnt); 16 | for(int i = 0; i < q; i++) { 17 | int t; cin >> t; 18 | auto itr = find(v.begin(), v.end(), t); 19 | if(itr == v.end()) printf("%d not found\n", t); 20 | else printf("%d found at %d\n", t, (itr - v.begin()) + 1); 21 | } 22 | } 23 | return 0; 24 | } -------------------------------------------------------------------------------- /ch7/uva11059.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main(void) { 6 | // 数据范围小,直接暴力O(n^2),当然还有其他做法:前缀和O(n^2) 7 | // 但是这道题在这本教材的定位,是暴力 8 | int a[20], n; 9 | int cnt = 0; 10 | while(scanf("%d", &n) != EOF) { 11 | for(int i = 0; i < n; i++) scanf("%d", &a[i]); 12 | // 注意用int会溢出 13 | long long ans = 0; 14 | for(int i = 0; i < n; i++) { 15 | // 注意用int会溢出 16 | long long t = 1; 17 | for(int j = i; j < n; j++) { 18 | t *= a[j]; 19 | if(t > ans) ans = t; 20 | } 21 | } 22 | printf("Case #%d: The maximum product is %lld.\n\n", ++cnt, ans); 23 | } 24 | return 0; 25 | } -------------------------------------------------------------------------------- /ch6/uva679.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int N = 524300; 7 | bool a[N]; 8 | int d, n; 9 | 10 | 11 | // 超时版本。。。N * 19 = 1e7,单组用例的时间复杂度已经很高了 12 | // 需要利用小球的序号和下落方向的关系 13 | int drop() { 14 | int ans = 1; 15 | for(int i = 1; i < d; i++) { 16 | int t = ans; 17 | if(a[t]) ans = ans * 2 + 1; 18 | else ans *= 2; 19 | a[t] = !a[t]; 20 | } 21 | return ans; 22 | } 23 | 24 | int main(void) { 25 | int T; scanf("%d", &T); 26 | while(T--) { 27 | int x; 28 | scanf("%d%d", &d, &x); 29 | memset(a, 0, sizeof a); 30 | for(int i = 0; i < x -1; i++) drop(); 31 | printf("%d\n", drop()); 32 | } 33 | return 0; 34 | } -------------------------------------------------------------------------------- /ch5/uva156.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | // 重要的是,如何判断2个字符是否互为anangrams 9 | // 变为小写字母,并排序 10 | string normalize(string& str) { 11 | string ans; 12 | for(int i = 0; i < str.size(); i++) 13 | ans += tolower(str[i]); 14 | sort(ans.begin(), ans.end()); 15 | return ans; 16 | } 17 | 18 | int main(void) { 19 | string str; 20 | vector v; 21 | unordered_map map; 22 | while(cin >> str, str != "#") { 23 | v.push_back(str); 24 | map[normalize(str)]++; 25 | } 26 | sort(v.begin(), v.end()); 27 | for(int i = 0; i < v.size(); i++) 28 | if(map[normalize(v[i])] == 1) 29 | cout << v[i] << endl; 30 | return 0; 31 | } -------------------------------------------------------------------------------- /ch4/uva1339.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | int cnt1[26], cnt2[26]; 8 | 9 | int main() { 10 | string enc; 11 | string ori; 12 | while(cin >> enc) { 13 | cin >> ori; 14 | memset(cnt1, 0, sizeof cnt1); 15 | memset(cnt2, 0, sizeof cnt2); 16 | int n = ori.size(); 17 | for(int i = 0; i < n; i++) 18 | cnt1[enc[i] - 'A']++; 19 | for(int i = 0; i < n; i++) 20 | cnt2[ori[i] - 'A']++; 21 | sort(cnt1, cnt1 + 26); 22 | sort(cnt2, cnt2 + 26); 23 | bool flag = true; 24 | for(int i = 0; i < 26 && flag; i++) 25 | if(cnt1[i] != cnt2[i]) flag = false; 26 | printf(flag ? "YES\n" : "NO\n"); 27 | } 28 | return 0; 29 | } -------------------------------------------------------------------------------- /ch5/uva1594.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | // 1. 直接枚举1000次,最后判断是否全为0,复杂度1e6 7 | // 2. 每走一步,判断一次是否全为0(或者和第一个序列相同) 8 | int main(void) { 9 | int T; int n; 10 | cin >> T; 11 | while(T--) { 12 | cin >> n; 13 | vector v(n); 14 | for(int i = 0; i < n; i++) cin >> v[i]; 15 | for(int i = 0; i < 1000; i++) { 16 | int t = v[0]; 17 | for(int j = 0; j < n - 1; j++) { 18 | v[j % n] = abs(v[j % n] - v[(j + 1) % n]); 19 | } 20 | v[n - 1] = abs(v[n - 1] - t); 21 | } 22 | bool zeroflag = true; 23 | for(int i = 0; i < n; i++) 24 | if(v[i] != 0) {puts("LOOP"), zeroflag = false; break;} 25 | if(zeroflag) puts("ZERO"); 26 | } 27 | return 0; 28 | } -------------------------------------------------------------------------------- /ch7/permut.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | // a子集 7 | // cur子集元素数量 8 | // n总元素数量 9 | // ele集合 10 | // 复杂度:O(选择s的复杂度) * O(2**n) 11 | void print_subset(int ele[], int tmp[], int n, int cur) { 12 | for(int i = 0; i < cur; i++) printf(i < cur - 1 ? "%d" : "%d\n", tmp[i]); 13 | // 枚举元素编号 14 | // 如果是散列,则s = cur ? map[tmp[cur - 1]] + 1 : 0; 15 | int s = cur ? find(ele, ele + n, tmp[cur - 1]) - ele + 1 : 0; 16 | // printf("s : %d\n", s); 17 | for(int i = s; i < n; i++) { 18 | tmp[cur] = ele[i]; 19 | // printf("choose index : %d, val : %d\n", i, ele[i]); 20 | print_subset(ele, tmp, n, cur + 1); 21 | } 22 | } 23 | 24 | int main(void) { 25 | int set[] = {1, 2, 3, 4}; 26 | int tmp[4] = {0}; 27 | print_subset(set, tmp, 4, 0); 28 | return 0; 29 | } -------------------------------------------------------------------------------- /ch6/uva11988-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int N = 100010; 7 | char a[N]; 8 | int ne[N], tt, cur, idx = 1; 9 | char str[N]; 10 | 11 | // 太奇怪了,将ne[0]设置为-1,会比设置为0快10ms... 12 | int main(void) { 13 | while(scanf("%s", str) != EOF) { 14 | int len = strlen(str); 15 | ne[0] = -1; 16 | cur = tt = 0, idx = 1; 17 | for(int i = 0; i < len; i++) { 18 | char ch = str[i]; 19 | if(ch == '[') cur = 0; 20 | else if(ch == ']') cur = tt; 21 | else { 22 | a[idx] = ch, ne[idx] = ne[cur], ne[cur] = idx; 23 | if(cur == tt) tt = idx; 24 | cur = idx, idx++; 25 | } 26 | } 27 | for(int i = ne[0]; i != -1; i = ne[i]) 28 | putchar(a[i]); 29 | puts(""); 30 | } 31 | return 0; 32 | } -------------------------------------------------------------------------------- /ch7/uva10976.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main(void) { 8 | #ifdef LOCAL 9 | freopen("uva10976.in", "r", stdin); 10 | freopen("uva10976.out", "w", stdout); 11 | #endif 12 | int k; 13 | vector> v; 14 | while(scanf("%d", &k) != EOF) { 15 | for(int y = k + 1; y > 2 * k; y++) { 16 | int x = k * y / (y - k); 17 | if((k * y) % (y - k)) continue; 18 | v.push_back({x, y}); 19 | } 20 | printf("%d\n", v.size()); 21 | for(auto & p : v) printf("1/%d = 1/%d + 1/%d\n", k, p.first, p.second); 22 | v.clear(); 23 | } 24 | return 0; 25 | } 26 | 27 | // 这题需要思考枚举的边界条件 28 | // 枚举x,根据x计算出y,x >= y 29 | // 那么x的枚举范围是什么呢?因为x, y > 0,所以,k < x 30 | // 又因为x >= y, 1/x <= 1/y, 1/k = 1/x + 1/y <= 2/y, y <= 2k 31 | // xy = kx + ky, x = ky/(y - k) -------------------------------------------------------------------------------- /arrayandstring/uva1586.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const int N = 100; 6 | char s[N]; 7 | 8 | double solve() { 9 | double res = 0; 10 | for(int i = 0; s[i]; i++) { 11 | char c = s[i]; 12 | double val; 13 | if(c == 'C') val = 12.01; 14 | else if(c == 'H') val = 1.008; 15 | else if(c == 'O') val = 16.00; 16 | else if(c == 'N') val = 14.01; 17 | int cnt = 0; 18 | while(s[i + 1] && isdigit(s[i + 1])) 19 | cnt = cnt * 10 + (s[++i] - '0'); 20 | if(!cnt) cnt = 1; 21 | res += val * cnt; 22 | } 23 | return res; 24 | } 25 | 26 | int main(void) { 27 | int T; 28 | scanf("%d", &T); 29 | while(T--) { 30 | memset(s, 0, sizeof s); 31 | scanf("%s", &s); 32 | // printf("%s\n", s); 33 | printf("%.3lf\n", solve()); 34 | } 35 | return 0; 36 | } -------------------------------------------------------------------------------- /ch6/uva514.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int N = 1010; 7 | int a[N]; 8 | int n; 9 | 10 | bool solve() { 11 | stack stk; 12 | int cnt = 0; 13 | for(int i = 0; i < n; i++) { 14 | int t = a[i]; 15 | if((stk.size() && stk.top() != t) && cnt > t) return false; 16 | while(cnt < t) stk.push(++cnt); 17 | if(stk.size() && stk.top() == t) stk.pop(); 18 | } 19 | return true; 20 | } 21 | 22 | int main(void) { 23 | bool first = true; 24 | while(scanf("%d", &n), n) { 25 | while(true) { 26 | int t; scanf("%d", &t); 27 | if(!t) break; 28 | a[0] = t; 29 | for(int i = 1; i < n; i++) 30 | scanf("%d", &t), a[i] = t; 31 | if(solve()) puts("Yes"); 32 | else puts("No"); 33 | } 34 | puts(""); 35 | } 36 | return 0; 37 | } -------------------------------------------------------------------------------- /ch5/uva1595.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | typedef pair pii; 8 | const int N = 10010; 9 | 10 | void solve(int n) { 11 | int l = N, r = -N; 12 | set dots; 13 | for(int i = 0; i < n; i++) { 14 | int a, b; scanf("%d%d", &a, &b); 15 | dots.insert({a, b}); 16 | if(a < l) l = a; 17 | if(a > r) r = a; 18 | } 19 | double mid = (l + r) / 2.0; 20 | for(auto& t : dots) 21 | if(!dots.count({-(t.first - mid) + mid, t.second})) { 22 | puts("NO"); return; 23 | } 24 | puts("YES"); 25 | } 26 | 27 | int main(void) { 28 | int T; cin >> T; 29 | while(T--) { 30 | int n; cin >> n; 31 | solve(n); 32 | } 33 | return 0; 34 | } 35 | // 3 36 | // 5 37 | // -2 5 38 | // 0 0 39 | // 6 5 40 | // 4 0 41 | // 2 3 42 | // 4 43 | // 2 3 44 | // 0 4 45 | // 4 0 46 | // 0 0 47 | // 4 48 | // 5 14 49 | // 6 10 50 | // 5 10 51 | // 6 14 -------------------------------------------------------------------------------- /ch4/uva133.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int N = 30; 7 | bool st[N]; 8 | 9 | int main(void) { 10 | int n, k, m; 11 | while(scanf("%d%d%d", &n, &k, &m) && n) { 12 | int rest = n; 13 | int a = 0, b = n + 1; 14 | memset(st, 0, sizeof st); 15 | st[a] = st[b] = true; 16 | while(rest) { 17 | for(int i = 0; i < k; i++) { 18 | while(a = a % n + 1, st[a]); 19 | } 20 | for(int i = 0; i < m; i++) { 21 | while(b = (b - 2 + n) % n + 1, st[b]); 22 | } 23 | if(rest != n) putchar(','); 24 | if(a == b) { 25 | rest--; printf("%3d", a); 26 | st[a] = true; 27 | } else { 28 | rest -= 2; 29 | printf("%3d%3d", a, b); 30 | st[a] = st[b] = true; 31 | } 32 | } 33 | puts(""); 34 | } 35 | return 0; 36 | } -------------------------------------------------------------------------------- /ch5/uva1593.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int N = 1010; 8 | 9 | vector tab[N]; 10 | int width[100]; 11 | 12 | int main(void) { 13 | string line; 14 | int row = 0; 15 | while(getline(cin, line)) { 16 | stringstream ss(line); 17 | string word; 18 | int col = 0; 19 | while(ss >> word) { 20 | if(word.size() > width[col]) 21 | width[col] = word.size(); 22 | tab[row].push_back(word); 23 | col++; 24 | } 25 | row++; 26 | } 27 | for(int i = 0; i < row; i++) { 28 | for(int j = 0; j < tab[i].size(); j++) { 29 | if(j > 0) printf(" "); 30 | auto& word = tab[i][j]; cout << word; 31 | for(int k = 0; j < tab[i].size() - 1 32 | && k < width[j] - word.size(); k++) 33 | printf(" "); 34 | } 35 | puts(""); 36 | } 37 | return 0; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /ch5/uva10815.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | set dict; 8 | 9 | // 也可以用cin >> str后,将str中非字母修改成space 10 | // 再将str扔进stringstream, 然后ss >> str 11 | bool read_word() { 12 | string word; 13 | char ch; 14 | while((ch = getchar()) != EOF && !isalpha(ch)); 15 | if(ch == EOF) return false; 16 | do word += tolower(ch); 17 | while(ch = getchar(), isalpha(ch)); 18 | if(word.size()) dict.insert(word); 19 | return word.size(); 20 | } 21 | 22 | bool read_word2() { 23 | string word; cin >> word; 24 | for(int i = 0; i < word.size(); i++) 25 | if(isalpha(word[i])) word[i] = tolower(word[i]); 26 | else word[i] = ' '; 27 | stringstream ss(word); 28 | bool flag = false; 29 | while(ss >> word) flag = true, dict.insert(word); 30 | return flag; 31 | } 32 | 33 | int main(void) { 34 | string str; 35 | while(read_word()); 36 | for(auto& str : dict) 37 | cout << str << endl; 38 | return 0; 39 | } -------------------------------------------------------------------------------- /ch5/uva12100.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int n, m; 8 | int a[10]; 9 | 10 | bool is_prior(int priority) { 11 | for(int i = priority + 1; i <= 9; i++) 12 | if(a[i]) return false; 13 | return true; 14 | } 15 | 16 | void solve() { 17 | queue q; 18 | memset(a, 0, sizeof a); 19 | for(int i = 0; i < n; i++) { 20 | int t; cin >> t; q.push(t); 21 | a[t]++; 22 | } 23 | int cnt = 0; 24 | while(true) { 25 | // cout << cnt << ":" << m << endl; 26 | int t = q.front(); 27 | if(!is_prior(t)) q.pop(), q.push(t); 28 | else { 29 | ++cnt; 30 | if(m == 0) {printf("%d\n", cnt); return;} 31 | q.pop(); a[t]--; 32 | } 33 | m = (m - 1 + q.size()) % q.size(); 34 | } 35 | } 36 | 37 | int main(void) { 38 | int T; scanf("%d", &T); 39 | while(T--) { 40 | // cout << endl; 41 | scanf("%d%d", &n, &m); solve(); 42 | } 43 | return 0; 44 | } -------------------------------------------------------------------------------- /arrayandstring/uva1368.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int M = 60, N = 1000; 5 | char a[M][N]; 6 | char res[N]; 7 | int m, n; 8 | char dna[4] = {'A', 'C', 'G', 'T'}; 9 | 10 | int index(char ch) { 11 | for(int i = 0; i < 4; i++) 12 | if(ch == dna[i]) return i; 13 | return -1; 14 | } 15 | 16 | int main() { 17 | int T; scanf("%d", &T); 18 | while(T--) { 19 | scanf("%d%d", &m, &n); 20 | int map[4]; 21 | for(int i = 0; i < m; i++) scanf("%s", a[i]); 22 | memset(res, 0, sizeof res); 23 | int dist = 0; 24 | for(int j = 0; j < n; j++) { 25 | memset(map, 0, sizeof map); 26 | for(int i = 0; i < m; i++) { 27 | map[index(a[i][j])]++; 28 | } 29 | int maxi = 0; 30 | for(int i = 0; i < 4; i++) 31 | if(map[i] > map[maxi]) maxi = i; 32 | res[j] = dna[maxi]; 33 | dist += m -map[maxi]; 34 | } 35 | printf("%s\n%d\n", res, dist); 36 | } 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /ch6/uva297-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int N = 32; 7 | int buf[N][N], cnt; 8 | 9 | void draw(string& s, int& p, int r, int c, int len) { 10 | char ch = s[p++]; 11 | if(ch == 'p') { 12 | len /= 2; 13 | draw(s, p, r, c + len, len); 14 | draw(s, p, r, c, len); 15 | draw(s, p, r + len, c, len); 16 | draw(s, p, r + len, c + len, len); 17 | } else if(ch == 'f') { 18 | for(int i = r; i < r + len; i++) 19 | for(int j = c; j < c + len; j++) 20 | if(!buf[i][j]) buf[i][j] = 1, cnt++; 21 | } 22 | } 23 | 24 | // 来自紫书的思路:不构造树,直接模拟画画 25 | int main(void) { 26 | int T; scanf("%d\n", &T); 27 | while(T--) { 28 | memset(buf, 0, sizeof(buf)); 29 | cnt = 0; 30 | for(int i = 0; i < 2; i++) { 31 | string s; 32 | getline(cin, s); 33 | int p = 0; 34 | draw(s, p, 0, 0, N); 35 | } 36 | printf("There are %d black pixels.\n", cnt); 37 | } 38 | return 0; 39 | } -------------------------------------------------------------------------------- /ch4/uva489.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int chance, rest; 7 | bool win, lose; 8 | 9 | void guess(string& str1, string& str2, int idx) { 10 | char ch = str2[idx]; 11 | 12 | bool valid = false; 13 | for(int i = 0; i < str1.size(); i++) 14 | if(ch == str1[i]) rest--, str1[i] = ' ', valid = true; 15 | 16 | if(!valid) chance--; 17 | if(!rest) win = true; 18 | if(!chance) lose = true; 19 | } 20 | 21 | int main() { 22 | int rnd; 23 | while(cin >> rnd, rnd != -1) { 24 | string str1, str2; 25 | cin >> str1 >> str2; 26 | win = lose = false; 27 | chance = 7, rest = str1.size(); 28 | for(int i = 0; i < str2.size(); i++) { 29 | guess(str1, str2, i); 30 | if(win || lose) break; 31 | } 32 | string ans; 33 | printf("Round %d\n", rnd); 34 | if(win) ans = "You win."; 35 | else if(lose) ans = "You lose."; 36 | else ans = "You chickened out."; 37 | cout << ans << endl; 38 | } 39 | return 0; 40 | } -------------------------------------------------------------------------------- /ch7/uva12325.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | typedef long long ll; 7 | 8 | int main(void) { 9 | int rnd = 0; 10 | int T; 11 | scanf("%d", &T); 12 | // const int INT_MAX = (1 << 31) - 1; 13 | while(T--) { 14 | int n, s1, v1, s2, v2; 15 | scanf("%d%d%d%d%d", &n, &s1, &v1, &s2, &v2); 16 | if(s1 > s2) swap(s1, s2), swap(v1, v2); 17 | // 用long long只是为了使得max函数的参数类型相同 18 | ll ans = 0; 19 | // 说明较大的s2比n小太多 20 | // 而且,s1 < s2 < 65536, s1 * s2 <= n 21 | if(n / s2 >= (1 << 16)) { 22 | // 用long long为了防止溢出 23 | for(ll i = 0; i <= s1; i++) 24 | ans = max(ans, v2 * i + (n - s2 * i) / s1 * v1); 25 | for(ll i = 0; i <= s2; i++) 26 | ans = max(ans, v1 * i + (n - s1 * i) / s2 * v2); 27 | } else { 28 | for(ll i = 0; s2 * i <= n; i++) 29 | ans = max(ans, v2 * i + (n - s2 * i) / s1 * v1); 30 | } 31 | printf("Case #%d: %lld\n", ++rnd, ans); 32 | } 33 | return 0; 34 | } -------------------------------------------------------------------------------- /ch6/uva536.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct Node { 8 | char val; 9 | Node *left, *right; 10 | Node(char val) : val(val), left(NULL), right(NULL) {} 11 | }; 12 | 13 | char po[27], io[27]; 14 | 15 | 16 | void post_dfs(Node* root) { 17 | if(!root) return; 18 | post_dfs(root->left); 19 | post_dfs(root->right); 20 | putchar(root->val); 21 | } 22 | 23 | auto rebuild(int pl, int pr, int il, int ir) -> Node* { 24 | if(pl > pr) return NULL; 25 | auto ans = new Node(po[pl]); 26 | // pl是根节点索引 27 | int i = il; 28 | for(; i <= ir; i++) 29 | if(io[i] == po[pl]) break; 30 | int llen = i - il; 31 | ans->left = rebuild(pl + 1, pl + llen, il, i - 1); 32 | ans->right = rebuild(pl + llen + 1, pr, i + 1, ir); 33 | return ans; 34 | } 35 | 36 | int main(void) { 37 | while(scanf("%s", po) != EOF) { 38 | scanf("%s", io); 39 | auto root = rebuild(0, strlen(po) - 1, 0, strlen(po) - 1); 40 | post_dfs(root); 41 | printf("\n"); 42 | } 43 | return 0; 44 | } -------------------------------------------------------------------------------- /ch6/uva673.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | char line[150]; 10 | 11 | bool solve() { 12 | fgets(line, 150, stdin); 13 | int n = strlen(line) - 1; 14 | stack stk; 15 | for(int i = 0; i < n; i++) { 16 | if(stk.empty()) { 17 | if(line[i] == ')' || line[i] == ']') return false; 18 | else stk.push(line[i]); 19 | } 20 | else { 21 | char ch = stk.top(); 22 | if(line[i] == '(' || line[i] == '[') stk.push(line[i]); 23 | else if(ch == '(' && line[i] == ')') stk.pop(); 24 | else if(ch == '[' && line[i] == ']') stk.pop(); 25 | else return false; 26 | } 27 | } 28 | return stk.empty(); 29 | } 30 | 31 | int main(void) { 32 | #ifdef LOCAL 33 | freopen("uva673.in", "r", stdin); 34 | freopen("uva673.out", "w", stdout); 35 | #endif 36 | int T; scanf("%d\n", &T); 37 | while(T--) { 38 | if(solve()) puts("Yes"); 39 | else puts("No"); 40 | } 41 | return 0; 42 | } -------------------------------------------------------------------------------- /ch6/uva712.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | // 根据x后的序数取数字,这个好办 9 | // 问题是:如何根据变量,决定答案的位置呢? 10 | // 其实也不难,给满二叉树编号 11 | // 叶子节点从左到右的编号是2 ** n ... 2 ** (n + 1) 12 | 13 | int order[10]; 14 | char str[10]; 15 | char leafs[130]; 16 | 17 | int main(void) { 18 | #ifdef LOCAL 19 | freopen("uva712.in", "r", stdin); 20 | freopen("uva712.out", "w", stdout); 21 | #endif 22 | int n, m; 23 | int casenum = 0; 24 | while(cin >> n, n) { 25 | for(int i = 1; i <= n; i++) { 26 | scanf("%s", str); 27 | order[i] = str[1] - '0'; 28 | } 29 | scanf("%s%d\n", leafs, &m); 30 | string ans; 31 | for(int i = 0; i < m; i++) { 32 | int num = 1; 33 | scanf("%s", str); 34 | for(int j = 1; j <= n; j++) { 35 | if(str[order[j] - 1] == '0') num *= 2; 36 | else num = num * 2 + 1; 37 | } 38 | ans += leafs[num - (int)pow(2, n)]; 39 | } 40 | printf("S-Tree #%d:\n%s\n\n", ++casenum, ans.c_str()); 41 | } 42 | return 0; 43 | } -------------------------------------------------------------------------------- /ch6/uva442.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | 7 | typedef pair pii; 8 | typedef long long ll; 9 | pii arr[26]; 10 | 11 | void solve(string& expr) { 12 | stack stk; 13 | if(expr[0] != '(') {puts("0"); return;} 14 | ll ans = 0; 15 | for(int i = 0; i < expr.size(); i++) { 16 | char ch = expr[i]; 17 | if(ch == ')') { 18 | auto b = stk.top(); stk.pop(); 19 | auto a = stk.top(); stk.pop(); 20 | stk.pop(); 21 | if(a.second != b.first) { 22 | puts("error"); 23 | return; 24 | } else ans += (ll)a.first * a.second * b.second; 25 | stk.push({a.first, b.second}); 26 | } else if(ch == '(') stk.push({-1, -1}); 27 | else stk.push(arr[ch - 'A']); 28 | } 29 | printf("%lld\n", ans); 30 | } 31 | 32 | int main(void) { 33 | int n; cin >> n; 34 | for(int i = 0; i < n; i++) { 35 | char a; int b, c; 36 | cin >> a >> b >> c; 37 | arr[a - 'A'] = {b, c}; 38 | } 39 | string expr; 40 | while(cin >> expr) { 41 | solve(expr); 42 | } 43 | return 0; 44 | } -------------------------------------------------------------------------------- /ch7/uva725.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | bool is_uni(int n, int cnt[]) { 7 | // 补0 8 | while(n < 10000) n *= 10; 9 | while(n) { 10 | if(cnt[n % 10]++ > 0) return false; 11 | n /= 10; 12 | } 13 | return true; 14 | } 15 | 16 | void solve(int n) { 17 | // 枚举分母,判断是否有效 18 | // 通过分母 * n计算出分子,判断是否有效 19 | // 若分子分母都有效,则打印 20 | // 21 | // 分母的范围?01234 - 分母*n超过5位 22 | // 通过一个数组,记录数字的出现情况 23 | int cnt[10]; 24 | bool found = false; 25 | for(int down = 1234; ; down++) { 26 | memset(cnt, 0, sizeof(cnt)); 27 | if(!is_uni(down, cnt)) continue; 28 | int up = down * n; 29 | if(up >= 1e5) break; 30 | if(is_uni(up, cnt)) { 31 | found = true; 32 | printf("%05d / %05d = %d\n", up, down, n); 33 | } 34 | } 35 | if(!found) printf("There are no solutions for %d.\n", n); 36 | } 37 | 38 | int main(void) { 39 | int rnd = 0; 40 | int n; 41 | while(scanf("%d", &n), n) { 42 | if(rnd++ > 0) puts(""); 43 | solve(n); 44 | } 45 | return 0; 46 | } 47 | 48 | // 除了上述思路,还可以用rujia liu的,将2个数放进数组,排序再判断唯一性 -------------------------------------------------------------------------------- /ch7/uva524.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | 4 | using namespace std; 5 | 6 | int n, arr[20]; 7 | bool used[20]; 8 | 9 | // 判断素数可以优化 10 | bool is_prime(int x) { 11 | if(x == 1) return false; 12 | for(int i = 2; i * i <= x; i++) 13 | if(x % i == 0) return false; 14 | return true; 15 | } 16 | 17 | void solve(int idx) { 18 | if(idx == n) { 19 | if(!is_prime(1 + arr[n - 1])) return; 20 | for(int i = 0; i < n; i++) 21 | printf(i ? " %d" : "%d", arr[i]); 22 | puts(""); 23 | return; 24 | } 25 | for(int i = 1; i <= n; i++) { 26 | if(!used[i] && is_prime(arr[idx - 1] + i)) { 27 | used[i] = true; 28 | arr[idx] = i; 29 | solve(idx + 1); 30 | used[i] = false; 31 | } 32 | } 33 | } 34 | 35 | int main(void) { 36 | #ifdef LOCAL 37 | freopen("uva524.in", "r", stdin); 38 | freopen("uva524.out", "w", stdout); 39 | #endif 40 | int cnt = 0; 41 | arr[0] = 1; 42 | while(~scanf("%d", &n)) { 43 | if(cnt) puts(""); 44 | used[1] = true; 45 | printf("Case %d:\n", ++cnt); 46 | solve(1); 47 | } 48 | return 0; 49 | } 50 | 51 | // DFS -------------------------------------------------------------------------------- /ch6/uva439.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | #define x first 8 | #define y second 9 | 10 | typedef pair pii; 11 | 12 | int sx, sy, tx, ty; 13 | int dist[8][8]; 14 | int dx[8] = {2, 2, 1, -1, -2, -2, -1, 1}; 15 | int dy[8] = {-1, 1, 2, 2, 1, -1, -2, -2}; 16 | 17 | int solve() { 18 | memset(dist, -1, sizeof(dist)); 19 | queue q; 20 | q.push({sx, sy}); 21 | dist[sx][sy] = 0; 22 | while(q.size()) { 23 | auto t = q.front(); q.pop(); 24 | if(t.x == tx && t.y == ty) return dist[tx][ty]; 25 | for(int i = 0; i < 8; i++) { 26 | int a = t.x + dx[i], b = t.y + dy[i]; 27 | if(a < 0 || a >= 8 || b < 0 || b >= 8) continue; 28 | if(dist[a][b] != -1) continue; 29 | dist[a][b] = dist[t.x][t.y] + 1; 30 | q.push({a, b}); 31 | } 32 | } 33 | return -1; 34 | } 35 | 36 | int main(void) { 37 | char from[3], to[3]; 38 | while(scanf("%s", from) != EOF) { 39 | scanf("%s", to); 40 | sy = from[0] - 'a', sx = from[1] - '1'; 41 | ty = to[0] - 'a', tx = to[1] - '1'; 42 | printf("To get from %s to %s takes %d knight moves.\n", from, to, solve()); 43 | } 44 | return 0; 45 | } -------------------------------------------------------------------------------- /ch6/uva10305.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | const int N = 110; 9 | int n, m; 10 | // 邻接表 11 | int h[N], e[N * N], ne[N * N], idx; 12 | int in[N]; 13 | 14 | void init() { 15 | memset(h, -1, sizeof(h)); 16 | memset(in, 0, sizeof(in)); 17 | idx = 0; 18 | } 19 | 20 | void add(int a, int b) { 21 | e[idx] = b, ne[idx] = h[a], h[a] = idx++; 22 | } 23 | 24 | void solve() { 25 | vector v; 26 | queue q; 27 | for(int i = 1; i <= n; i++) 28 | if(!in[i]) v.push_back(i), q.push(i); 29 | 30 | while(q.size()) { 31 | auto t = q.front(); q.pop(); 32 | for(int i = h[t]; i != -1; i = ne[i]) { 33 | int j = e[i]; 34 | if(--in[j] == 0) q.push(j), v.push_back(j); 35 | } 36 | } 37 | for(int i = 0; i < v.size(); i++) 38 | printf(i > 0 ? " %d" : "%d", v[i]); 39 | puts(""); 40 | } 41 | 42 | int main(void) { 43 | while(scanf("%d%d", &n, &m), n) { 44 | init(); 45 | for(int i = 0; i < m; i++) { 46 | int a, b; scanf("%d%d", &a, &b); 47 | if(!a) break; 48 | add(a, b); 49 | in[b]++; 50 | } 51 | solve(); 52 | } 53 | return 0; 54 | } -------------------------------------------------------------------------------- /ch8/uva120.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | const int maxn = 100; 8 | int n; 9 | int arr[maxn+1]; 10 | 11 | void flip(int i) { 12 | int l = i, r = n; 13 | while(l < r) swap(arr[l++], arr[r--]); 14 | } 15 | 16 | bool read_input() { 17 | string s; 18 | if(!getline(cin, s)) return false; 19 | cout << s << endl; 20 | stringstream ss(s); 21 | int t; 22 | n = 0; 23 | while(ss >> t) arr[++n] = t; 24 | flip(1); 25 | return true; 26 | } 27 | 28 | void solve() { 29 | // find unprocessed max val 30 | // its pos has 3 conditions: 31 | // 1. at correct pos: do nothing 32 | // 2. at top: flip to correct pos 33 | // 3. at mid: flip to top, then flip to correct pos 34 | priority_queue heap; 35 | for(int i = 1; i <= n; i++) heap.push(arr[i]); 36 | for(int i = 1; i <= n; i++) { 37 | int t = heap.top(); heap.pop(); 38 | int k = i; 39 | while(arr[k] != t) k++; 40 | if(k != i) { 41 | if(k == n) flip(i), printf("%d ", i); 42 | else flip(k), flip(i), printf("%d %d ", k, i); 43 | } 44 | } 45 | printf("0\n"); 46 | } 47 | 48 | int main(void) { 49 | while(read_input()) solve(); 50 | return 0; 51 | } -------------------------------------------------------------------------------- /ch6/uva699.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | struct Node { 9 | int val; 10 | Node *left, *right; 11 | Node(int val) : val(val), left(NULL), right(NULL) {} 12 | }; 13 | 14 | Node *root; 15 | unordered_map map; 16 | 17 | void build(Node *u) { 18 | int l, r; 19 | scanf("%d", &l); 20 | if(l != -1) 21 | u->left = new Node(l), build(u->left); 22 | scanf("%d", &r); 23 | if(r != -1) 24 | u->right = new Node(r), build(u->right); 25 | } 26 | 27 | void dfs(Node* node, int x) { 28 | if(!node) return; 29 | map[x] += node->val; 30 | dfs(node->left, x - 1); 31 | dfs(node->right, x + 1); 32 | } 33 | 34 | int main(void) { 35 | for(int i = 1; ; i++) { 36 | int val; scanf("%d", &val); 37 | if(val == -1) break; 38 | else root = new Node(val); 39 | map.clear(); 40 | build(root); 41 | dfs(root, 0); 42 | printf("Case %d:\n", i); 43 | vector> v; 44 | for(auto& t : map) v.push_back(t); 45 | sort(v.begin(), v.end()); 46 | for(int i = 0; i < v.size(); i++) 47 | printf(i > 0 ? " %d" : "%d", v[i].second); 48 | printf("\n\n"); 49 | } 50 | return 0; 51 | } -------------------------------------------------------------------------------- /ch7/uva1374.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int n; 10 | vector v; 11 | 12 | bool dfs(int d, int maxd, int tmax) { 13 | if(v[d] == n) { 14 | printf("%d\n", d); 15 | return true; 16 | } 17 | if(d == maxd) return false; 18 | // cout << "d:" << d << ':' << v[d] << endl; 19 | tmax = max(tmax, v[d]); 20 | // 接下来可能达到的最大值是,max ** (2 ** (maxd - d)) 21 | if((tmax << (maxd - d)) < n) return false; 22 | 23 | for(int i = d; i >= 0; i--) { 24 | int t1 = v[d], t2 = v[i]; 25 | int t = t1 + t2; 26 | if(v.size() - 1 < d + 1) v.push_back(t); 27 | else v[d+1] = t; 28 | if(dfs(d+1, maxd, tmax)) return true; 29 | t = t1 - t2; 30 | if(t > 0) { 31 | v[d+1] = t; 32 | if(dfs(d+1, maxd, tmax)) return true; 33 | } 34 | } 35 | return false; 36 | } 37 | 38 | int main(void) { 39 | #ifdef LOCAL 40 | freopen("uva1374.in", "r", stdin); 41 | freopen("uva1374.out", "w", stdout); 42 | #endif 43 | v.push_back(1); 44 | while(scanf("%d", &n) == 1, n) { 45 | for(int maxd = 0; ; maxd++) 46 | if(dfs(0, maxd, 1)) break; 47 | } 48 | return 0; 49 | } 50 | 51 | // IDA, 经典。。。 -------------------------------------------------------------------------------- /ch6/uva572.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | const int N = 110; 6 | int m, n; 7 | char grid[N][N]; 8 | int dx[] = {-1, 0, 1, 1, 1, 0, -1, -1}, dy[] = {-1, -1, -1, 0, 1, 1, 1, 0}; 9 | 10 | int ans; 11 | 12 | // 常量数组8连通 13 | // void dfs(int sx, int sy) { 14 | // grid[sx][sy] = ' '; 15 | // for(int i = 0; i < 8; i++) { 16 | // int a = sx + dx[i], b = sy + dy[i]; 17 | // if(a < 0 || a >= m || b < 0 || b >= n) continue; 18 | // if(grid[a][b] != '@') continue; 19 | // dfs(a, b); 20 | // } 21 | // } 22 | 23 | // 二重循环8连通 24 | void dfs(int sx, int sy) { 25 | if(sx < 0 || sx >= m || sy < 0 || sy >= n) return; 26 | if(grid[sx][sy] != '@') return; 27 | grid[sx][sy] = ' '; 28 | for(int dr = -1; dr <= 1; dr++) 29 | for(int dc = -1; dc <= 1; dc++) dfs(sx + dr, sy + dc); 30 | } 31 | 32 | int main(void) { 33 | while(scanf("%d%d\n", &m, &n) != EOF && m > 0) { 34 | for(int i = 0; i < m; i++) 35 | scanf("%s", grid[i]); 36 | // puts(""); 37 | // for(int i = 0; i < m; i++) 38 | // printf("%s\n", grid[i]); 39 | ans = 0; 40 | for(int i = 0; i < m; i++) 41 | for(int j = 0; j < n; j++) 42 | if(grid[i][j] == '@') ans++, dfs(i, j); 43 | printf("%d\n", ans); 44 | } 45 | return 0; 46 | } -------------------------------------------------------------------------------- /ch6/uva548.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int N = 10010; 7 | int por[N], ior[N], l[N], r[N]; 8 | int n; 9 | 10 | bool read_order(int* a) { 11 | n = 0; 12 | string str; 13 | if(!getline(cin, str)) return false; 14 | stringstream ss(str); 15 | int val; 16 | while(ss >> val) a[n++] = val; 17 | // return n > 0 will be more robust 18 | return true; 19 | } 20 | 21 | int build(int pl, int pr, int il, int ir) { 22 | if(pl > pr || il > ir) return -1; 23 | // pr是根节点索引 24 | int i = il; 25 | for(; i <= ir; i++) 26 | if(ior[i] == por[pr]) break; 27 | int llen = i - il; 28 | l[pr] = build(pl, pl + llen - 1, il, i - 1); 29 | r[pr] = build(pl + llen, pr - 1, i + 1, ir); 30 | return pr; 31 | } 32 | 33 | int ans, idx; 34 | 35 | void dfs(int val, int x) { 36 | if(x == -1) return; 37 | val += por[x]; 38 | if(l[x] == -1 && r[x] == -1) { 39 | if(val < ans) { 40 | ans = val; idx = x; 41 | } else if(val == ans) { 42 | if(por[idx] > por[x]) idx = x; 43 | } 44 | return; 45 | } 46 | dfs(val, l[x]); 47 | dfs(val, r[x]); 48 | } 49 | 50 | int main(void) { 51 | while(read_order(ior)) { 52 | read_order(por); 53 | ans = 0x3f3f3f3f; 54 | build(0, n - 1, 0, n - 1); 55 | dfs(0, n - 1); 56 | printf("%d\n", por[idx]); 57 | } 58 | return 0; 59 | } -------------------------------------------------------------------------------- /ch6/uva1600-b.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | const int N = 25; 9 | int g[N][N], dist[N][N][N]; 10 | int m, n, k; 11 | int dx[] = {0, 0, -1, 1}, dy[] = {-1, 1, 0, 0}; 12 | 13 | struct Node { 14 | int r, c, k; 15 | }; 16 | 17 | bool is_unvalid(int a, int b) { 18 | return a < 1 || a > m || b < 1 || b > n; 19 | } 20 | 21 | int solve() { 22 | memset(dist, -1, sizeof(dist)); 23 | queue q; 24 | dist[1][1][0] = 0; 25 | q.push({1, 1, 0}); 26 | while(q.size()) { 27 | auto t = q.front(); q.pop(); 28 | if(t.r == m && t.c == n) return dist[t.r][t.c][0]; 29 | for(int i = 0; i < 4; i++) { 30 | int a = t.r + dx[i], b = t.c + dy[i]; 31 | if(is_unvalid(a, b)) continue; 32 | int nk = g[a][b] ? t.k + 1 : 0; 33 | if(dist[a][b][nk] < 0 && nk <= k) { 34 | dist[a][b][nk] = dist[t.r][t.c][t.k] + 1; 35 | q.push({a, b, nk}); 36 | } 37 | } 38 | } 39 | return -1; 40 | } 41 | 42 | int main(void) { 43 | #ifdef LOCAL 44 | freopen("uva1600.in", "r", stdin); 45 | freopen("uva1600.out", "w", stdout); 46 | #endif 47 | int T; scanf("%d", &T); 48 | while(T--) { 49 | scanf("%d%d%d", &m, &n, &k); 50 | for(int i = 1; i <= m; i++) 51 | for(int j = 1; j <= n; j++) 52 | scanf("%d", &g[i][j]); 53 | printf("%d\n", solve()); 54 | } 55 | return 0; 56 | } -------------------------------------------------------------------------------- /ch6/uva297.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | struct Node { 6 | char val; 7 | Node* child[4]; 8 | Node(char val) : val(val) {} 9 | }; 10 | 11 | Node *root1, *root2; 12 | int sum; 13 | 14 | char readchar() { 15 | char ch; 16 | while(ch = getchar(), !isalpha(ch)); 17 | return ch; 18 | } 19 | 20 | // assert u != NULL 21 | void build(Node* u) { 22 | if(!u || u->val != 'p') return; 23 | for(int i = 0; i < 4; i++) { 24 | u->child[i] = new Node(readchar()); 25 | build(u->child[i]); 26 | } 27 | } 28 | 29 | void make_empty_child(Node* u) { 30 | for(int i = 0; i < 4; i++) { 31 | u->child[i] = new Node('e'); 32 | } 33 | } 34 | 35 | void solve(Node *u, Node *v, int val) { 36 | // 其中一个是黑,则全黑,sum += val, return 37 | // 其中一个p,另一个白,则为白的分配4个白色子节点,开始子节点的匹配 38 | // 2个白,直接return 39 | // 2个p,开始子节点的匹配 40 | if(u->val == 'f' || v->val == 'f') {sum += val; return;} 41 | if(u->val == 'e' && v->val == 'e') return; 42 | if(u->val == 'e') make_empty_child(u); 43 | if(v->val == 'e') make_empty_child(v); 44 | for(int i = 0; i < 4; i++) { 45 | solve(u->child[i], v->child[i], val / 4); 46 | } 47 | } 48 | 49 | int main(void) { 50 | int T; scanf("%d", &T); 51 | while(T--) { 52 | root1 = new Node(readchar()); 53 | build(root1); 54 | root2 = new Node(readchar()); 55 | build(root2); 56 | sum = 0; 57 | solve(root1, root2, 1024); 58 | printf("There are %d black pixels.\n", sum); 59 | } 60 | return 0; 61 | } -------------------------------------------------------------------------------- /ch6/uva10129-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | bool g[26][26], visited[26][26]; 9 | char word[1010]; 10 | int deg[26]; 11 | 12 | bool dfs(int u) { 13 | bool ans = false; 14 | for(int i = 0; i < 26; i++) 15 | if(g[u][i] && !visited[u][i]) { 16 | visited[u][i] = true; 17 | ans = true; 18 | dfs(i); 19 | } 20 | return ans; 21 | } 22 | 23 | int main(void) { 24 | int T; scanf("%d", &T); 25 | while(T--) { 26 | int n; scanf("%d", &n); 27 | memset(g, 0, sizeof(g)); 28 | memset(deg, 0, sizeof(deg)); 29 | memset(visited, 0, sizeof(visited)); 30 | for(int i = 0; i < n; i++) { 31 | scanf("%s", word); 32 | int size = strlen(word); 33 | int ch1 = word[0] - 'a', ch2 = word[size - 1] - 'a'; 34 | g[ch1][ch2] = true; 35 | deg[ch1]--, deg[ch2]++; 36 | } 37 | int cnt = 0; 38 | for(int i = 0; i < 26; i++) 39 | if(dfs(i)) cnt++; 40 | 41 | vector v; 42 | for(int i = 0; i < 26; i++) 43 | if(deg[i] != 0) v.push_back(deg[i]); 44 | sort(v.begin(), v.end()); 45 | bool flag = false; 46 | if(v.size() == 0) flag = true; 47 | if(v.size() == 2 && v[0] == -1 && v[1] == 1) flag = true; 48 | if(cnt != 1) flag = false; 49 | if(flag) puts("Ordering is possible."); 50 | else puts("The door cannot be opened."); 51 | } 52 | return 0; 53 | } -------------------------------------------------------------------------------- /ch7/uva129.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | 4 | using namespace std; 5 | 6 | int n, L, cnt; 7 | char str[100]; 8 | 9 | void print_ans(int n) { 10 | for(int i = 0; i < n; ) { 11 | for(int j = 0; j < 16 && i < n; j++) { 12 | if(j > 0) putchar(' '); 13 | for(int k = 0; k < 4 && i < n; k++, i++) { 14 | putchar(str[i]); 15 | } 16 | } 17 | puts(""); 18 | } 19 | printf("%d\n", n); 20 | } 21 | 22 | bool is_hard(int n) { 23 | for(int i = 1; 2 * i <= n; i++) { 24 | bool same = true; 25 | for(int j = n - 1; j > n - 1 - i; j--) { 26 | if(str[j] != str[j - i]) { 27 | same = false; break; 28 | } 29 | } 30 | if(same) return false; 31 | } 32 | return true; 33 | } 34 | 35 | void dfs(int idx) { 36 | for(int i = 0; cnt < n && i < L; i++) { 37 | str[idx] = 'A' + i; 38 | if(is_hard(idx + 1)) { 39 | if(++cnt == n) { 40 | print_ans(idx + 1); 41 | } 42 | dfs(idx + 1); 43 | } 44 | } 45 | } 46 | 47 | int main(void) { 48 | #ifdef LOCAL 49 | freopen("uva129.in", "r", stdin); 50 | freopen("uva129.out", "w", stdout); 51 | #endif 52 | while(scanf("%d%d", &n, &L), n) { 53 | cnt = 0; 54 | dfs(0); 55 | } 56 | return 0; 57 | } 58 | 59 | // 从前L个字母中,选取字符组成hard seq 60 | // 求字母升序的第n大的seq 61 | // hard seq: 相邻的sub seq不相同 62 | // 使用递归枚举,每增加一个字符s[i],就要判断以这个字符结尾的 63 | // 长度为偶数的字符串,逐个比较前后2部分,如果不符合,那么回溯,如果符合那么打印并且继续 64 | // 这个判断,可以优化吗?emmmm,先不管优化了哈哈哈 -------------------------------------------------------------------------------- /ch5/uva540.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main(void) { 9 | int t; 10 | int cnt = 0; 11 | while(scanf("%d", &t) != EOF, t) { 12 | unordered_map idmap; 13 | for(int i = 0; i < t; i++) { 14 | int k; cin >> k; 15 | for(int j = 0; j < k; j++) { 16 | int ele; cin >> ele; 17 | idmap[ele] = i; 18 | } 19 | } 20 | // 这题,也可以为每个team都声明一个queue,放在数组中 21 | // 然后队列只需要保存queue的arr idx 22 | queue*> q; 23 | char cmd[10]; 24 | unordered_map> qmap; 25 | cnt++; 26 | printf("Scenario #%d\n", cnt); 27 | for(;;) { 28 | char cmd[10]; 29 | scanf("%s", cmd); 30 | if(cmd[0] == 'S') break; 31 | if(cmd[0] == 'E') { 32 | int x; cin >> x; 33 | int id = idmap[x]; 34 | if(qmap.count(id)) { 35 | qmap[id].push(x); 36 | } else { 37 | qmap[id] = queue(); 38 | q.push(&qmap[id]); 39 | q.back()->push(x); 40 | } 41 | } else if(cmd[0] == 'D') { 42 | auto& tq = *q.front(); 43 | int ele = tq.front(); 44 | if(tq.size() == 1) q.pop(), qmap.erase(idmap[ele]); 45 | else tq.pop(); 46 | printf("%d\n", ele); 47 | } 48 | } 49 | puts(""); 50 | } 51 | return 0; 52 | } -------------------------------------------------------------------------------- /arrayandstring/uva202.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | // ans 9 | // b a 10 | // 余数 11 | // 每除一次,若余数不为0,则余数乘10 12 | // 若除数重复出现,说明出现了循环 13 | 14 | const int N = 30100; 15 | int st[N]; 16 | 17 | // 0.(0) 18 | // 3.(0) 19 | // 3.04(0) 20 | // 3.1(13) 21 | void solve(int ia, int ib) { 22 | memset(st, -1, sizeof st); 23 | int a = ia, b = ib; 24 | vector ans; 25 | int len = 0; 26 | while(true) { 27 | // 判断除数是否重复 28 | if(~st[a]) { 29 | len = ans.size() - st[a]; 30 | break; 31 | } 32 | ans.push_back(a / b); 33 | st[a] = ans.size() - 1; 34 | a = 10 * (a % b); 35 | } 36 | printf("%d/%d = %d.", ia, ib, ans[0]); 37 | int i = 1; 38 | for(; i < st[a]; i++) 39 | printf("%d", ans[i]); 40 | int t = i; 41 | printf("("); 42 | // 注意一个细节,初始的a作为除数重复出现,那么余数应该多输出一位 43 | for(; i < t + len && i <= 50; i++) 44 | printf("%d", ans[i % ans.size()]); 45 | if(i >= 50) printf("..."); 46 | printf(")\n"); 47 | printf(" %d = number of digits in repeating cycle\n", len); 48 | puts(""); 49 | // 1/3 0,1 50 | // 10/3 3,1 51 | // 10/3 3,1 52 | } 53 | 54 | int main(void) { 55 | // solve(76, 25); 56 | // solve(5, 43); 57 | // solve(1, 397); 58 | // solve(1, 6); 59 | // solve(5, 7); 60 | // solve(1, 250); 61 | // solve(300, 31); 62 | // solve(655, 990); 63 | // solve(0, 1); 64 | // solve(5, 5); 65 | int a, b; 66 | for(int i = 0; scanf("%d", &a) != EOF; i++) { 67 | scanf("%d", &b); 68 | solve(a, b); 69 | } 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /ch4/uva213.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int read_len() { 7 | int len = 0; 8 | for(int i = 0; i < 3; i++) { 9 | char ch; 10 | while(ch = getchar(), ch != '0' && ch != '1'); 11 | len = len * 2 + (ch - '0'); 12 | } 13 | return len; 14 | } 15 | 16 | int get_idx(string& pat) { 17 | int cnt = 0; 18 | for(int i = 1; i < pat.size(); i++) { 19 | for(int j = 0; j < (int)pow(2, i) - 1; j++) 20 | cnt++; 21 | } 22 | int num = 0; 23 | for(int i = 0; i < pat.size(); i++) 24 | num = num * 2 + (pat[i] - '0'); 25 | return num + cnt; 26 | } 27 | 28 | bool read_header(string& header) { 29 | char ch; 30 | while(ch = getchar(), ch == '\n' || ch == '\r'); 31 | if(ch == EOF) return false; 32 | header += ch; 33 | while(ch = getchar(), ch != '\n' && ch != '\r') { 34 | header += ch; 35 | } 36 | return true; 37 | } 38 | 39 | int main(void) { 40 | string header; 41 | while(read_header(header)) { 42 | int len = 0; 43 | string ans; 44 | while(len = read_len(), len) { 45 | while(true) { 46 | string pat; 47 | bool flag = false; 48 | for(int i = 0; i < len; i++) { 49 | char ch; 50 | while(ch = getchar(), ch != '0' && ch != '1'); 51 | pat += ch; 52 | if(ch == '0') flag = true; 53 | } 54 | if(flag) ans += header[get_idx(pat)]; 55 | else break; 56 | } 57 | } 58 | cout << ans << endl; 59 | header.clear(); 60 | } 61 | return 0; 62 | } -------------------------------------------------------------------------------- /ch5/uva400.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // L = longest filename 8 | // C = 1 + (60 - L) / (L + 2) 9 | // R = N / C + (N % C ? 1 : 0) = (N - 1) / C + 1; 10 | // 用vector存储文件名,排序 11 | // 每行输出最多 C 个filename 12 | // 左对齐,宽度L+2,最后一列宽度L 13 | // 设idx为filename索引 14 | // 文件输出会被分成2个部分,左边比右边的行数更多 15 | // 左边:c = idx / R, r = idx % R 16 | // 因此,idx = (idx / R * R) + idx % R = c * R + r 17 | // 右边:c = (idx - 左边) / (R - 1) + 左边列数, r = (idx - 左边) % (R - 1) 18 | // 因此,idx = (c - 左边列数) * (R-1) + r + 左边 19 | // 左边列数 = N % C,左边 = 左边列数 * R 20 | // 因此,idx = (c - 左边列数) * (R - 1) + r + 左边列数 * R, 21 | // idx = c * (R - 1) + r + 左边列数 22 | // 你也以为是这样做?那么就错了。。。 23 | // 你以为是这样? 24 | // 1 4 6 25 | // 2 5 7 26 | // 3 27 | // 其实是这样 28 | // 1 4 7 29 | // 2 5 30 | // 3 6 31 | 32 | const int W = 60; 33 | 34 | int main(void) { 35 | int n; 36 | string s_line(W, '-'); 37 | while(cin >> n) { 38 | vector v(n); 39 | int L = 0; 40 | for(int i = 0; i < n; i++) { 41 | cin >> v[i]; 42 | if(v[i].size() > L) L = v[i].size(); 43 | } 44 | sort(v.begin(), v.end()); 45 | int C = 1 + (W - L) / (L + 2); 46 | int R = (n - 1) / C + 1; 47 | int l_col = n % C; 48 | cout << s_line << endl; 49 | for(int i = 0; i < R; i++) { 50 | for(int j = 0; j < C; j++) { 51 | int idx = j * R + i; 52 | if(idx >= n) break; 53 | printf("%s", v[idx].c_str()); 54 | int t = (j < C - 1 ? L + 2 : L) - v[idx].size(); 55 | for(int i = 0; i < t; i++) putchar(' '); 56 | } 57 | puts(""); 58 | } 59 | } 60 | return 0; 61 | } -------------------------------------------------------------------------------- /ch6/uva12166.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | typedef long long ll; 9 | 10 | void solve(string& str) { 11 | stack stk; 12 | unordered_map map; 13 | ll tmp = 0; 14 | for(int i = 0; i < str.size(); i++) { 15 | char ch = str[i]; 16 | if(ch == '[') stk.push(ch); 17 | else if(ch == ',') { 18 | if(tmp != 0) { 19 | map[tmp * (ll)pow(2, stk.size())]++; 20 | tmp = 0; 21 | } 22 | } else if(ch == ']') { 23 | if(tmp != 0) { 24 | map[tmp * (ll)pow(2, stk.size())]++; 25 | tmp = 0; 26 | } 27 | stk.pop(); 28 | } else if(isdigit(ch)) tmp = tmp * 10 + (ch - '0'); 29 | } 30 | int maxcnt = 0, cnt = 0; 31 | for(auto& t : map) { 32 | if(t.second > maxcnt) maxcnt = t.second; 33 | cnt += t.second; 34 | } 35 | printf("%d\n", cnt - maxcnt); 36 | } 37 | 38 | int main(void) { 39 | int T; scanf("%d\n", &T); 40 | while(T--) { 41 | string str; 42 | getline(cin, str); 43 | solve(str); 44 | } 45 | return 0; 46 | } 47 | 48 | // https://www.luogu.com.cn/blog/goucw/solution-uva12166 49 | // 用m代替最小的质量,画出几个天平,观察发现: 50 | // 在一个平衡的天平中,所有物品的重量weight 乘 2 ** depth之后,数值相等 51 | // 问题就变成了,寻找weight 乘 2 ** depth之后,数值相等的数量 52 | // 这个数量就是满足要求的数量,那么总数量 - 数值相等的数量 = 答案:需要修改重量的数量 53 | // 这道题的关键是,通过作图,观察到平衡的天平里物品重量之间的关系 54 | // 如果问最小重量,那么就是数值 / 2 ** max depth 55 | 56 | // 启发:所以说动手画图真的很重要!!! 57 | 58 | // 那么问题来了:如何解析表达式,准确找到每个数值的深度呢? 59 | // [[1, 2], 6] 60 | // [[[1, 2], 2], 3] 61 | // [[[1, 2], [3, [2, 6]]], 7] 62 | // 使用栈,遍历表达式字符 63 | // 遇到[直接入栈 64 | // 遇到整数,depth == stk.size 65 | // 遇到,跳过 66 | // 遇到],stk.pop() -------------------------------------------------------------------------------- /ch7/uva690.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int maxn = 20; 7 | int used[maxn * 10 + 10][5]; 8 | char rev[5][maxn + 1]; 9 | int n; 10 | 11 | bool read_input() { 12 | if(scanf("%d\n", &n) == EOF || n == 0) return false; 13 | for(int i = 0; i < 5; i++) 14 | scanf("%s", &rev[i]); 15 | return true; 16 | } 17 | 18 | void mark(int time, int x) { 19 | for(int j = 0; j < n; j++) { 20 | for(int i = 0; i < 5; i++) { 21 | if(rev[i][j] == 'X') used[time+j][i] = x; 22 | } 23 | } 24 | } 25 | 26 | bool check(int time) { 27 | for(int j = 0; j < n; j++) { 28 | for(int i = 0; i < 5; i++) { 29 | if(rev[i][j] == 'X' && used[time+j][i] != -1) 30 | return false; 31 | } 32 | } 33 | return true; 34 | } 35 | 36 | int lastpos; 37 | int minstep; 38 | 39 | void dfs(int x, int s) { 40 | if(s >= lastpos) return; 41 | if(x == 10) { 42 | lastpos = s; 43 | return; 44 | } 45 | for(int time = s; time <= min(s + n, lastpos); time++) { 46 | // 即使time这一步能够成功,那么剩下10-x-1=9-x步 47 | if(time + (9-x) * minstep >= lastpos) return; 48 | if(!check(time)) continue; 49 | mark(time, x); 50 | dfs(x+1,time); 51 | mark(time, -1); 52 | } 53 | } 54 | 55 | int solve() { 56 | memset(used, -1, sizeof used); 57 | lastpos = 9 * n; 58 | mark(0, 0); 59 | // 预测最小步长 60 | for(int i = 0; i < n; i++) 61 | if(check(i)) {minstep = i; break;} 62 | dfs(1,0); 63 | return lastpos + n; 64 | } 65 | 66 | int main(void) { 67 | while(read_input()) { 68 | printf("%d\n", solve()); 69 | } 70 | return 0; 71 | } 72 | 73 | // 810ms... 74 | // 如果前面有2个任务已经放置了,那么第三个的位置必然大于等于2*minstep, 75 | // 而不可能小于2*minstep,所以更新f(i)是纯粹增加开销。。。 -------------------------------------------------------------------------------- /ch6/uva10526.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int maxn = 210; 8 | int n; 9 | char buf[maxn][maxn]; 10 | 11 | bool is_node_label(char ch) { 12 | // emmmm,题目数据和题面不一样,题目数据是允许#表示节点的 13 | return isprint(ch) && ch != ' ' && ch != '-' && ch != '|'; 14 | } 15 | 16 | void dfs(int sx, int sy) { 17 | printf("%c(", buf[sx][sy]); 18 | if(sx + 1 >= n || buf[sx + 1][sy] != '|') {putchar(')'); return;} 19 | int x = sx + 2, y = sy; 20 | while(y - 1 >= 0 && buf[x][y - 1] == '-') y--; 21 | while(buf[x][y] == '-' && buf[x + 1][y]) { 22 | char ch = buf[x + 1][y]; 23 | if(is_node_label(ch)) dfs(x + 1, y); 24 | y++; 25 | } 26 | putchar(')'); 27 | } 28 | 29 | void solve() { 30 | n = 0; 31 | for(;;) { 32 | fgets(buf[n], maxn, stdin); 33 | if(buf[n][0] == '#') break; 34 | else n++; 35 | } 36 | putchar('('); 37 | if(n) { 38 | for(int i = 0; i < strlen(buf[0]); i++) 39 | if(buf[0][i] != ' ') {dfs(0, i); break;} 40 | } 41 | printf(")\n"); 42 | } 43 | 44 | int main(void) { 45 | #ifdef LOCAL 46 | freopen("uva10526.in", "r", stdin); 47 | freopen("uva10526.out", "w", stdout); 48 | #endif 49 | int T; 50 | fgets(buf[0], maxn, stdin); 51 | sscanf(buf[0], "%d", &T); 52 | while(T--) solve(); 53 | return 0; 54 | } 55 | 56 | // 构建一颗多叉树做DFS 57 | // 如何将文本解析为一棵树 58 | 59 | // 方案1:构建树后做DFS 60 | // 读取节点,读取节点下一行 61 | // 如果节点下一行的首字符是#,说明这棵树构建完成 62 | // 否则,说明这一层的节点,有孩子节点 63 | // 记录下方有竖线的节点!!! 64 | // 读取一行横线,一行字符 65 | // 第x段横线下的字符,对应第x个下方有竖线的节点的子节点 66 | 67 | // 初始化,将根节点放入队列 68 | // 队列保存,从左到右有孩子的上层节点 69 | // 读取后续3行,遍历当前队列中的元素,对每个元素做以下的事情: 70 | // 在第一行中确定一段横线的范围,在第二行中读入横线下的字符作为子节点 71 | // 如果第3行首字符不是#,那么还要判断每个子节点下方是否竖线,如果有说明有子节点,放入队列 72 | 73 | // 方案2 from Rujia Liu:读取每棵树到2-d数组,递归处理数组,生成字符串 -------------------------------------------------------------------------------- /ch5/uva1592-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | typedef pair pii; 8 | 9 | const int N = 10010, M = 20; 10 | int n, m; 11 | // 这个超慢的。。。 12 | map maparr[N][M]; 13 | string row[M]; 14 | map idmap; 15 | int strid; 16 | 17 | int ID(string& str) { 18 | if(idmap.count(str)) return idmap[str]; 19 | idmap[str] = strid; 20 | return strid++; 21 | } 22 | 23 | void readrow() { 24 | string tmp; 25 | int ch; 26 | while(ch = getchar(), !(ch >= ' ' && ch <= '~')); 27 | tmp += ch; 28 | for(int i = 1; i <= m; i++) { 29 | for(;;) { 30 | ch = getchar(); 31 | if(ch == ',') {row[i] = tmp; tmp.clear(); break;} 32 | if(ch == '\n' || ch == '\r') { 33 | row[i] = tmp; return; 34 | } 35 | tmp += ch; 36 | } 37 | } 38 | } 39 | 40 | bool check(int cur_row) { 41 | for(int i = 1; i <= m; i++) { 42 | for(int j = i + 1; j <= m; j++) { 43 | pii t = {ID(row[i]), ID(row[j])}; 44 | // string t = ID(row[i]) + "," + ID(row[j]); 45 | // cout << t << endl; 46 | if(maparr[i][j].count(t)) { 47 | puts("NO"); 48 | printf("%d %d\n", maparr[i][j][t], cur_row); 49 | printf("%d %d\n", i, j); 50 | return false; 51 | } 52 | maparr[i][j][t] = cur_row; 53 | } 54 | } 55 | return true; 56 | } 57 | 58 | int main(void) { 59 | while(cin >> n >> m) { 60 | bool flag = true; 61 | for(int i = 0; i < M; i++) 62 | for(int j = 0; j < M; j++) maparr[i][j].clear(); 63 | for(int i = 1; i <= n; i++) { 64 | readrow(); 65 | if(flag && !check(i)) flag = false; 66 | } 67 | if(flag) printf("YES\n"); 68 | } 69 | return 0; 70 | } -------------------------------------------------------------------------------- /ch5/uva1592.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | typedef pair pii; 9 | 10 | const int N = 10010, M = 20; 11 | int n, m; 12 | int tab[N][M]; 13 | unordered_map idmap; 14 | int strid; 15 | 16 | int ID(string& str) { 17 | if(!idmap.count(str)) { 18 | idmap[str] = ++strid; 19 | } 20 | return idmap[str]; 21 | } 22 | 23 | void readrow(int row) { 24 | string tmp; 25 | int ch; 26 | while(ch = getchar(), !(ch >= ' ' && ch <= '~')); 27 | tmp += ch; 28 | for(int i = 1; i <= m; i++) { 29 | for(;;) { 30 | ch = getchar(); 31 | if(ch == ',') {tab[row][i] = ID(tmp); tmp.clear(); break;} 32 | if(ch == '\n' || ch == '\r') { 33 | tab[row][i] = ID(tmp); 34 | // cout << tmp << endl; 35 | return; 36 | } 37 | tmp += ch; 38 | } 39 | } 40 | } 41 | 42 | void solve() { 43 | for(int i = 1; i <= m; i++) { 44 | for(int j = i + 1; j <= m; j++) { 45 | // unordered_map不能够用PII作为key 46 | map d; 47 | for(int k = 1; k <= n; k++) { 48 | pii t = {tab[k][i], tab[k][j]}; 49 | // cout << t.first << ":" << t.second << endl; 50 | if(d.count(t)) { 51 | puts("NO"); 52 | printf("%d %d\n", d[t], k); 53 | printf("%d %d\n", i, j); 54 | return; 55 | } 56 | d[t] = k; 57 | } 58 | } 59 | } 60 | printf("YES\n"); 61 | } 62 | 63 | int main(void) { 64 | while(cin >> n >> m) { 65 | strid = 0; 66 | idmap.clear(); 67 | for(int i = 1; i <= n; i++) 68 | readrow(i); 69 | solve(); 70 | } 71 | return 0; 72 | } -------------------------------------------------------------------------------- /ch7/uva690-d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int maxn = 20; 8 | bool used[maxn * 10 + 10][5]; 9 | char rev[5][maxn + 1]; 10 | int tab[maxn]; // 根据陈锋老师代码,一个时间最多只有一个单元被使用... 11 | vector offset; 12 | int n, f[11]; 13 | 14 | bool read_input() { 15 | if(scanf("%d\n", &n) == EOF || n == 0) return false; 16 | for(int i = 0; i < 5; i++) 17 | scanf("%s", &rev[i]); 18 | memset(tab, -1, sizeof tab); 19 | for(int j = 0; j < n; j ++) 20 | for(int i = 0; i < 5; i++) { 21 | if(rev[i][j] == 'X') tab[j] = i; 22 | } 23 | return true; 24 | } 25 | 26 | void mark(int time, bool val) { 27 | for(int j = 0; j < n; j++) { 28 | if(tab[j] != -1) used[time+j][tab[j]] = val; 29 | } 30 | } 31 | 32 | bool check(int time) { 33 | for(int j = 0; j < n; j++) { 34 | if(tab[j] != -1 && used[time+j][tab[j]]) return false; 35 | } 36 | return true; 37 | } 38 | 39 | void dfs(int x, int s, int mx) { 40 | if(x == mx) { 41 | f[mx] = min(s, f[mx]); 42 | return; 43 | } 44 | for(auto os : offset) { 45 | int time = s + os; 46 | if(time + f[mx-x] >= f[mx]) return; 47 | if(!check(time)) continue; 48 | mark(time, true); 49 | dfs(x+1,time, mx); 50 | mark(time, false); 51 | } 52 | } 53 | 54 | int solve() { 55 | mark(0, true); 56 | offset.clear(); 57 | for(int i = 0; i <= n; i++) 58 | if(check(i)) offset.push_back(i); 59 | 60 | memset(f, 0, sizeof f); 61 | for(int i = 1; i <= 10; i++) { 62 | f[i] = i * n; 63 | dfs(1, 0, i); 64 | } 65 | mark(0, false); 66 | return f[10] + n; 67 | } 68 | 69 | int main(void) { 70 | while(read_input()) { 71 | printf("%d\n", solve()); 72 | } 73 | return 0; 74 | } 75 | 76 | // 看了陈锋老师的解答。。。究极版本,f[i], 一维task, 稀疏步长 77 | // 20ms... -------------------------------------------------------------------------------- /ch5/uva12096.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | // 这题不能用unordered系列容器 4 | // #include 5 | // #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | // 第一想法是,用一个结构体表示集合 14 | // struct Set {int size; Set* a[N]} 15 | // 对于pointer like class, 我们还需要重写适当的copy ctor和dtor 16 | // 显然这很没必要 17 | // 所以,我们可以模拟这个结构体和指针 18 | // 用一个数组保存全部Set,idx就是Set的指针 19 | // (这个模拟指针的方法,有很多用处,模拟HashMap,linked-list都很有用) 20 | // 而Set中,保存了Set中子集的idx 21 | // 因此,利用STL中的set,就可以解决复制和销毁的时候内存管理的问题 22 | // set.size()就是cardinality 23 | 24 | #define ALL(x) x.begin(),x.end() 25 | 26 | typedef set Set; 27 | vector v; 28 | // 保证同样构造的Set是唯一的 29 | map set_ids; 30 | stack stk; 31 | 32 | int id(const Set& x) { 33 | if(set_ids.count(x)) return set_ids[x]; 34 | v.push_back(x); 35 | return set_ids[x] = v.size() - 1; 36 | } 37 | 38 | int main(void) { 39 | int w; cin >> w; 40 | for(int i = 0; i < w; i++) { 41 | int n; cin >> n; 42 | while(n--) { 43 | string cmd; cin >> cmd; 44 | if(cmd == "PUSH") stk.push(id(Set())); 45 | else if(cmd == "DUP") stk.push(id(v[stk.top()])); 46 | else { 47 | int a = stk.top(); stk.pop(); 48 | int b = stk.top(); stk.pop(); 49 | Set res; 50 | if(cmd == "UNION") 51 | set_union(ALL(v[a]), ALL(v[b]), inserter(res, res.begin())); 52 | else if(cmd == "INTERSECT") 53 | set_intersection(ALL(v[a]), ALL(v[b]), inserter(res, res.begin())); 54 | else if(cmd == "ADD") 55 | res = v[b], res.insert(a); 56 | stk.push(id(res)); 57 | } 58 | printf("%d\n", v[stk.top()].size()); 59 | } 60 | printf("***\n"); 61 | } 62 | return 0; 63 | } -------------------------------------------------------------------------------- /arrayandstring/uva227.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int N = 6; 7 | char a[N][N]; 8 | 9 | void get_empty_pos(int *x, int * y) { 10 | for(int i = 0; i < 5; i++) 11 | for(int j = 0; j < 5; j++) 12 | if(a[i][j] == ' ') { 13 | *x = i, *y = j; 14 | break; 15 | } 16 | } 17 | 18 | void get_pos(int* x, int* y, char op) { 19 | if(op == 'A') *x -= 1; 20 | else if(op == 'B') *x += 1; 21 | else if(op == 'L') *y -= 1; 22 | else if(op == 'R') *y += 1; 23 | } 24 | 25 | void print_matrix() { 26 | for(int i = 0; i < 5; i++) { 27 | for(int j = 0; j < 5; j++) { 28 | printf(j < 4 ? "%c " : "%c\n", a[i][j]); 29 | } 30 | } 31 | } 32 | 33 | bool valid_square(char ch) { 34 | return ch == ' ' || isalpha(ch); 35 | } 36 | 37 | bool read_matrix() { 38 | for(int i = 0; i < 5; i++) { 39 | char ch; 40 | while(!valid_square(ch = getchar())); 41 | if(ch == 'Z') return false; 42 | a[i][0] = ch; 43 | for(int j = 1; j < 5; j++) a[i][j] = getchar(); 44 | } 45 | return true; 46 | } 47 | 48 | bool solve() { 49 | int x = 0, y = 0; 50 | get_empty_pos(&x, &y); 51 | char op; 52 | bool valid = true; 53 | while((op = getchar()) != '0') { 54 | if(!isalpha(op) || !valid) continue; 55 | int dx = x, dy = y; 56 | get_pos(&dx, &dy, op); 57 | if(dx < 0 || dx > 4 || dy < 0 || dy > 4) valid = false; 58 | swap(a[x][y], a[dx][dy]); 59 | x = dx, y = dy; 60 | } 61 | return valid; 62 | } 63 | 64 | int main() { 65 | for(int i = 1; ; i++) { 66 | if(!read_matrix()) break; 67 | bool flag = solve(); 68 | if(i != 1) puts(""); 69 | printf("Puzzle #%d:\n", i); 70 | if(flag) print_matrix(); 71 | else printf("This puzzle has no final configuration.\n"); 72 | } 73 | return 0; 74 | } -------------------------------------------------------------------------------- /ch7/uva208.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | const int maxn = 25; 11 | int dest, path[maxn]; 12 | bool used[maxn]; 13 | int tot; 14 | vector map[maxn]; 15 | 16 | bool check_connectivity() { 17 | queue q; 18 | memset(used, false, sizeof(used)); 19 | q.push(1); 20 | used[1] = true; 21 | while(q.size()) { 22 | auto t = q.front(); q.pop(); 23 | if(t == dest) return true; 24 | for(auto next : map[t]) 25 | if(!used[next]) { 26 | used[next] = true; 27 | q.push(next); 28 | } 29 | } 30 | return false; 31 | } 32 | 33 | void dfs(int x, int cur) { 34 | if(used[x]) return; 35 | if(x == dest) { 36 | tot++; 37 | path[cur] = x; 38 | for(int i = 0; i <= cur; i++) 39 | printf(i > 0 ? " %d" : "%d", path[i]); 40 | puts(""); 41 | return; 42 | } 43 | used[x] = true; 44 | path[cur] = x; 45 | for(auto next : map[x]) dfs(next, cur + 1); 46 | used[x] = false; 47 | } 48 | 49 | void enum_routes() { 50 | memset(used, false, sizeof(used)); 51 | dfs(1, 0); 52 | } 53 | 54 | int main(void) { 55 | #ifdef LOCAL 56 | freopen("uva208.in", "r", stdin); 57 | freopen("uva208.out", "w", stdout); 58 | #endif 59 | int cnt = 0; 60 | while(scanf("%d", &dest) != EOF) { 61 | int a, b; 62 | for(int i = 0; i < maxn; i++) map[i].clear(); 63 | while(scanf("%d%d", &a, &b), a) 64 | map[a].push_back(b), map[b].push_back(a); 65 | for(int i = 0; i < maxn; i++) sort(map[i].begin(), map[i].end()); 66 | printf("CASE %d:\n", ++cnt); 67 | tot = 0; 68 | if(check_connectivity()) enum_routes(); 69 | printf("There are %d routes from the firestation to streetcorner %d.\n", tot, dest); 70 | } 71 | return 0; 72 | } -------------------------------------------------------------------------------- /ch7/uva690-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int maxn = 20; 8 | int used[maxn * 10 + 10][5]; 9 | char rev[5][maxn + 1]; 10 | vector tab[maxn]; 11 | int n; 12 | 13 | bool read_input() { 14 | if(scanf("%d\n", &n) == EOF || n == 0) return false; 15 | for(int i = 0; i < 5; i++) 16 | scanf("%s", &rev[i]); 17 | for(int j = 0; j < n; j++) tab[j].clear(); 18 | for(int j = 0; j < n; j ++) 19 | for(int i = 0; i < 5; i++) { 20 | if(rev[i][j] == 'X') tab[j].push_back(i); 21 | } 22 | return true; 23 | } 24 | 25 | void mark(int time, int x) { 26 | for(int j = 0; j < n; j++) { 27 | for(auto i : tab[j]) used[time+j][i] = x; 28 | } 29 | } 30 | 31 | bool check(int time) { 32 | for(int j = 0; j < n; j++) { 33 | for(auto i : tab[j]) 34 | if(used[time+j][i] != -1) return false; 35 | } 36 | return true; 37 | } 38 | 39 | int lastpos; 40 | int minstep; 41 | 42 | void dfs(int x, int s) { 43 | if(s >= lastpos) return; 44 | if(x == 10) { 45 | lastpos = s; 46 | return; 47 | } 48 | for(int time = s; time <= s + n; time++) { 49 | // 剩下k个任务,由于第一个任务步长是0,所以只需要k-1个步 50 | if(time + (10-x-1) * minstep >= lastpos) return; 51 | if(!check(time)) continue; 52 | mark(time, x); 53 | dfs(x+1,time); 54 | mark(time, -1); 55 | } 56 | } 57 | 58 | int solve() { 59 | memset(used, -1, sizeof used); 60 | lastpos = 9 * n; 61 | mark(0, 0); 62 | for(int i = 0; i <= n; i++) 63 | if(check(i)) {minstep = i; break;} 64 | dfs(1,0); 65 | return lastpos + n; 66 | } 67 | 68 | int main(void) { 69 | while(read_input()) { 70 | printf("%d\n", solve()); 71 | } 72 | return 0; 73 | } 74 | 75 | // vector版本,310ms... 将min(s+n, lastpos)改成s+n,280ms更快... 76 | // 1. 如果f(i)使用递归算出来的,那么f(i)是会比i*minstep小的, 77 | // 这样反而容易导致 time + f(i) >= lastpos的条件没那么容易触发,反而更慢。。。 78 | // 2. 但是一味的将f(i)变大也是没有根据的,会导致错误的结果 -------------------------------------------------------------------------------- /ch7/uva690-c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int maxn = 20; 8 | bool used[maxn * 10 + 10][5]; 9 | char rev[5][maxn + 1]; 10 | int tab[maxn]; // 根据陈锋老师代码,一个时间最多只有一个单元被使用... 11 | vector offset; 12 | int n; 13 | 14 | bool read_input() { 15 | if(scanf("%d\n", &n) == EOF || n == 0) return false; 16 | for(int i = 0; i < 5; i++) 17 | scanf("%s", &rev[i]); 18 | memset(tab, -1, sizeof tab); 19 | for(int j = 0; j < n; j ++) 20 | for(int i = 0; i < 5; i++) { 21 | if(rev[i][j] == 'X') tab[j] = i; 22 | } 23 | return true; 24 | } 25 | 26 | void mark(int time, bool val) { 27 | for(int j = 0; j < n; j++) { 28 | if(tab[j] != -1) used[time+j][tab[j]] = val; 29 | } 30 | } 31 | 32 | bool check(int time) { 33 | for(int j = 0; j < n; j++) { 34 | if(tab[j] != -1 && used[time+j][tab[j]]) return false; 35 | } 36 | return true; 37 | } 38 | 39 | int lastpos; 40 | int minstep; 41 | 42 | void dfs(int x, int s) { 43 | if(s >= lastpos) return; 44 | if(x == 10) { 45 | lastpos = s; 46 | return; 47 | } 48 | for(auto os : offset) { 49 | int time = s + os; 50 | if(time + (9-x) * minstep >= lastpos) return; 51 | if(!check(time)) continue; 52 | mark(time, true); 53 | dfs(x+1,time); 54 | mark(time, false); 55 | } 56 | } 57 | 58 | int solve() { 59 | lastpos = 9 * n; 60 | mark(0, true); 61 | offset.clear(); 62 | for(int i = 0; i <= n; i++) 63 | if(check(i)) offset.push_back(i); 64 | minstep = offset[0]; 65 | dfs(1,0); 66 | mark(0, false); 67 | return lastpos + n; 68 | } 69 | 70 | int main(void) { 71 | while(read_input()) { 72 | printf("%d\n", solve()); 73 | } 74 | return 0; 75 | } 76 | 77 | // vector版本,310ms... 将min(s+n, lastpos)改成s+n,280ms更快... 78 | // 1. 如果f(i)使用递归算出来的,那么f(i)是会比i*minstep小的, 79 | // 这样反而容易导致 time + f(i) >= lastpos的条件没那么容易触发,反而更慢。。。 80 | // 2. 但是一味的将f(i)变大也是没有根据的,会导致错误的结果 -------------------------------------------------------------------------------- /ch4/uva201-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | const int N = 15; 9 | bool h[N][N], v[N][N]; 10 | int n, m; 11 | 12 | // n * n点矩阵 13 | // m条边 14 | // 枚举每个点,从0 ... n - 1 15 | // 以每个点为左上角,枚举边长 1 ... min(n - 1 - x, n - 1 - y) 16 | // 对于每个左上角(x, y)和边长len确定的正方形,判断是否所有边都存在 17 | 18 | bool check_edge(int x, int y, int len, bool is_hori) { 19 | for(int i = 0; i < len; i++) { 20 | bool flag = is_hori ? h[x][y] : v[y][x]; 21 | if(!flag) return false; 22 | if(is_hori) y++; 23 | else x++; 24 | } 25 | return true; 26 | } 27 | 28 | bool check(int x, int y, int len) { 29 | // up , left, right, down 30 | int dx[4] = {0, 0, len, 0}; 31 | int dy[4] = {0, 0, 0, len}; 32 | for(int i = 0; i < 4; i++) { 33 | int tx = x + dx[i], ty = y + dy[i]; 34 | if(!check_edge(tx, ty, len, (i + 1) & 1)) 35 | return false; 36 | } 37 | return true; 38 | } 39 | 40 | void solve(int cnt) { 41 | map map; 42 | for(int i = 1; i <= n; i++) { 43 | for(int j = 1; j <= n; j++) { 44 | for(int len = 1; len <= min(n - i, n - j); len++) 45 | if(check(i, j, len)) map[len]++; 46 | } 47 | } 48 | if(cnt != 1) printf("\n**********************************\n\n"); 49 | printf("Problem #%d\n\n", cnt); 50 | if(!map.size()) printf("No completed squares can be found.\n"); 51 | for(auto p : map) { 52 | printf("%d square (s) of size %d\n", p.second, p.first); 53 | } 54 | } 55 | 56 | int main(void) { 57 | int cnt = 1; 58 | while(scanf("%d%d", &n, &m) != EOF) { 59 | memset(h, 0, sizeof h); 60 | memset(v, 0, sizeof v); 61 | for(int k = 0; k < m; k++) { 62 | char type; 63 | int i, j; 64 | cin >> type >> i >> j; 65 | if(type == 'H') h[i][j] = true; 66 | else if(type == 'V') v[i][j] = true; 67 | } 68 | solve(cnt); 69 | cnt++; 70 | } 71 | return 0; 72 | } -------------------------------------------------------------------------------- /ch6/uva1572.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int g[52][52]; 7 | 8 | // 0 undicovered, 1 discovered, 2 processed 9 | int st[52]; 10 | 11 | int ID(char a1, char a2) { 12 | return (a1 -'A') * 2 + (a2 == '+' ? 0 : 1); 13 | } 14 | 15 | void connect(char a1, char a2, char b1, char b2) { 16 | if(a1 == '0' || b1 == '0') return; 17 | int u = ID(a1, a2), v = ID(b1, b2) ^ 1; // u 能转换为 v符号相反的标号 18 | // printf("u:%d;v:%d\n", u, v); 19 | g[u][v] = true; 20 | } 21 | 22 | // return false if graph is not DAG 23 | // means the topsort failed 24 | bool dfs(int u) { 25 | st[u] = 1; 26 | for(int i = 0; i < 52; i++) 27 | if(g[u][i]) { 28 | if(st[i] == 1) return false; 29 | if(!st[i] && !dfs(i)) return false; 30 | } 31 | st[u] = 2; 32 | return true; 33 | } 34 | 35 | bool is_cycle_exist() { 36 | memset(st, 0, sizeof(st)); 37 | for(int i = 0; i < 52; i++) 38 | if(!st[i]) if(!dfs(i)) return true; 39 | return false; 40 | } 41 | 42 | int main() { 43 | int n; 44 | while(scanf("%d", &n) != EOF && n) { 45 | memset(g, 0, sizeof(g)); 46 | while(n--) { 47 | char s[10]; 48 | scanf("%s", s); 49 | for(int i = 0; i < 4; i++) 50 | for(int j = 0; j < 4; j++) if(i != j) 51 | connect(s[i*2], s[i*2+1], s[j*2], s[j*2+1]); 52 | } 53 | if(is_cycle_exist()) puts("unbounded"); 54 | else puts("bounded"); 55 | } 56 | return 0; 57 | } 58 | 59 | // 这道题,需要判断是否能组成无限大的结合物 60 | // 不同的原子相连的条件是:字母相同,电性相反 61 | // 观察几种集合物无限大的状况: 62 | // 1. 一个原子在直线上自相连 63 | // 2. 存在多个原子成同一直线自相连,其中一部分是循环(可能是两端,也可能是中间) 64 | // 特别说明:不是连通分量的数量不必须是1,只要有其中一个连通分量无限大就够了 65 | // 题目有个条件:正方形可以旋转或者翻转 66 | // 有了这个条件,即便互相吸引的边缘,分布在相邻位置而不是相对位置,一个单原子也能自相连 67 | // 所以,集合物无限大的情况就改变了: 68 | // 1. 一个原子循环 69 | // 2. 存在多个原子成同一直线自相连,其中一部分是循环(可能是两端,也可能是中间) 70 | // 3. 存在多个原子相连,其中一部分是循环(可能是两端,也可能是中间) 71 | // 显然,3种情况都有一个充分条件,存在循环!!! 72 | // 也就是一个标号通过循环之后,转换成了自己 73 | 74 | // 如何建模呢? 75 | // 我们继续观察,例如,一个A+00A-00原子,它能通过自循环,无限扩大 76 | // 原因是,A+ A- 能够连上 A+ 77 | // 也就是说,对于一对标号(x, y),x能够连上的标号,或者说能够转换成的标号,由y决定 78 | 79 | -------------------------------------------------------------------------------- /ch5/uva101.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // 用vector array模拟操作 8 | // 用一个array保存block当前所在的位置 9 | // 所有的操作,可以分解为以下的操作 10 | // 1. 将block i上方的block move to original pos 11 | // 2. 移动block i到指定位置 12 | // 3. 移动block i及其上方的block到指定位置 13 | // 无论如何移动,只在放置的时候更新pos 14 | // 解析命令: 15 | // move or pile决定了a上方的block是否需要还原 16 | // onto or over决定了b上方的block是否需要还原 17 | // 先读取move or pile 18 | // if move, pop的过程中,还原上方block(update pos) 19 | // if pile, pop的过程中,用stack存储 20 | // 读取onto or over 21 | // if onto, pop的过程中,还原上方block(update pos) 22 | // if over, 不用动b所在的pile 23 | // finally, pop stack, push_back to vector and update pos 24 | 25 | const int N = 30; 26 | int pos[N]; 27 | vector a[N]; 28 | stack stk; 29 | int n; 30 | 31 | void recover_above(int pi, int x) { 32 | for(int t = a[pi].back(); t != x; t = a[pi].back()) { 33 | a[pi].pop_back(); 34 | a[t].push_back(t), pos[t] = t; 35 | } 36 | } 37 | 38 | int main(void) { 39 | cin >> n; 40 | for(int i = 0; i < n; i++) 41 | a[i].push_back(i), pos[i] = i; 42 | string cmd1, cmd2; 43 | while(cin >> cmd1, cmd1 != "quit") { 44 | int from, to; 45 | cin >> from >> cmd2 >> to; 46 | int pf = pos[from], pt = pos[to]; 47 | if(from == to || pf == pt) continue; 48 | if(cmd1 == "move") { 49 | recover_above(pf, from); 50 | stk.push(a[pf].back()); 51 | a[pf].pop_back(); 52 | } else if(cmd1 == "pile") { 53 | while(true) { 54 | int t = a[pf].back(); a[pf].pop_back(); 55 | stk.push(t); 56 | if(t == from) break; 57 | } 58 | } 59 | if(cmd2 == "onto") recover_above(pt, to); 60 | while(stk.size()) { 61 | int t = stk.top(); stk.pop(); 62 | a[pt].push_back(t), pos[t] = pt; 63 | } 64 | } 65 | for(int i = 0; i < n; i++) { 66 | printf("%d:", i); 67 | for(int j = 0; j < a[i].size(); j++) 68 | printf(" %d", a[i][j]); 69 | puts(""); 70 | } 71 | return 0; 72 | } -------------------------------------------------------------------------------- /ch7/uva818.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int maxn = 16; 8 | int g[maxn][maxn], n; 9 | int comp_cnt; 10 | bool vis[maxn]; 11 | 12 | // whether the x bit from right is switched on 13 | bool on(int s, int x) { 14 | return s & (1 << x); 15 | } 16 | 17 | // whether the component has cycle 18 | bool dfs_fail(int x, int pre, int s) { 19 | if(vis[x]) return true; 20 | vis[x] = true; 21 | int t = pre == -1 ? 0 : 1; 22 | for(int i = 0; i < n; i++) { 23 | if(g[x][i] && !on(s,i) && i != pre) { 24 | if(++t > 2 || dfs_fail(i, x, s)) return true; 25 | } 26 | } 27 | return false; 28 | } 29 | 30 | // check whether each component has cycle and count components 31 | bool valid(int s, int t) { 32 | memset(vis, false, sizeof vis); 33 | int comp_cnt = 0; 34 | for(int i = 0; i < n; i++) { 35 | if(!vis[i] && !on(s, i)) { 36 | if(t < (++comp_cnt - 1) || dfs_fail(i, -1, s)) return false; 37 | } 38 | } 39 | return true; 40 | } 41 | 42 | // count the piece be opened 43 | int cal(int s) { 44 | int ans = 0; 45 | for(int i = 0; i < n; i++) 46 | if(on(s, i)) ans++; 47 | return ans; 48 | } 49 | 50 | // enum the open status of pieces 51 | // check whether it will has cycle or some pieces has more than 2 neighbours 52 | // and confirm the opened pieces amount should be sufficient to connect all components 53 | // which means opened pieces >= componets - 1 54 | int solve() { 55 | int ans = maxn; 56 | for(int s = 0; s < (1 << n); s++) { 57 | int t = cal(s); 58 | if(valid(s, t)) ans = min(t, ans); 59 | } 60 | return ans; 61 | } 62 | 63 | int main(void) { 64 | #ifdef LOCAL 65 | freopen("uva818.out", "w", stdout); 66 | #endif 67 | int cnt = 0; 68 | while(scanf("%d", &n) , n) { 69 | memset(g, 0, sizeof g); 70 | int a, b; 71 | while(scanf("%d%d", &a, &b), a != -1) 72 | g[a-1][b-1] = g[b-1][a-1] = 1; 73 | printf("Set %d: Minimum links to open is %d\n", ++cnt, solve()); 74 | } 75 | return 0; 76 | } -------------------------------------------------------------------------------- /ch6/uva122.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | // 将path排个序,可以发现,左子树的node会在右子树前面,而且父节点会在子节点前面 9 | // path长度相同的在同一层 10 | // 长度相同的排个序,就是正确的层次遍历顺序 11 | // 如何判断path给了重复值?path相同 12 | // 如何判断path没给?某个path的前缀不存在 13 | 14 | // 1. psi存起来 15 | // 2. 扔进set查重 16 | // 3. 枚举前缀 17 | // if complete 18 | // 排序输出 19 | // else print "not complete" 20 | #define x first 21 | #define y second 22 | typedef pair psi; 23 | 24 | // 长度小的层次比较浅 25 | // 长度相同的,比字典序 26 | int cmp(const psi& t1, const psi& t2) { 27 | if(t1.x.size() != t2.x.size()) return t1.x.size() < t2.x.size(); 28 | else return t1.x < t2.x; 29 | } 30 | 31 | bool solve() { 32 | vector v; 33 | for(;;) { 34 | char ch; 35 | while(ch = getchar(), isspace(ch)); 36 | if(ch == EOF) return false; 37 | ch = getchar(); 38 | if(ch == ')') break; 39 | int val = ch - '0'; 40 | while(ch = getchar(), ch != ',') 41 | val = val * 10 + (ch - '0'); 42 | string path; 43 | while(ch = getchar(), ch != ')') 44 | path += ch; 45 | v.push_back({path, val}); 46 | } 47 | // for(int i = 0; i < v.size(); i++) 48 | // cout << v[i].first << ":" << v[i].second << ' '; 49 | // cout << endl; 50 | set pset; 51 | for(int i = 0; i < v.size(); i++) { 52 | auto& t = v[i].x; 53 | if(pset.count(t)) { 54 | puts("not complete"); 55 | return true; 56 | } 57 | pset.insert(t); 58 | } 59 | for(int i = 0; i < v.size(); i++) { 60 | auto& t = v[i].x; 61 | for(int len = 0; len < t.size(); len++) 62 | if(!pset.count(t.substr(0, len))) { 63 | puts("not complete"); 64 | return true; 65 | } 66 | } 67 | sort(v.begin(), v.end(), cmp); 68 | for(int i = 0; i < v.size(); i++) { 69 | auto& t = v[i]; 70 | printf(i > 0 ? " %d" : "%d", v[i].y); 71 | } 72 | puts(""); 73 | return true; 74 | } 75 | 76 | int main(void) { 77 | while(solve()); 78 | return 0; 79 | } -------------------------------------------------------------------------------- /ch6/uva12657.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | // 正常情况下,0是头节点 6 | // inv的情况下,n + 1是头节点 7 | // 那么: 8 | // 1和2互换就好了,其他无区别 9 | 10 | // 不需要元素,因为指定位置的元素是确定的 11 | const int M = 100010; 12 | int l[M], r[M], n, m; 13 | bool inv; 14 | 15 | void print() { 16 | if(inv) { 17 | for(int i = l[n+1], cnt = 1; i != 0; i = l[i], cnt++) 18 | printf("%d ", i); 19 | } else { 20 | for(int i = r[0], cnt = 1; i != n + 1; i = r[i], cnt++) 21 | printf("%d ", i); 22 | } 23 | puts(""); 24 | } 25 | 26 | void init() { 27 | r[0] = 1, l[n + 1] = n; 28 | for(int i = 1; i <= n; i++) 29 | l[i] = i - 1, r[i] = i + 1; 30 | inv = false; 31 | } 32 | 33 | void swap_pos(int x, int y) { 34 | // assert x != y 35 | int t = l[x]; l[x] = l[y]; l[y] = t; 36 | r[l[x]] = x; r[l[y]] = y; 37 | t = r[x]; r[x] = r[y]; r[y] = t; 38 | l[r[x]] = x; l[r[y]] = y; 39 | } 40 | 41 | void move_left(int x, int y) { 42 | r[l[x]] = r[x], l[r[x]] = l[x]; 43 | l[x] = l[y], r[x] = y, r[l[y]] = x, l[y] = x; 44 | } 45 | 46 | void solve(int op) { 47 | if(op == 4) {inv = !inv; return;} 48 | int x, y; scanf("%d%d", &x, &y); 49 | if(op == 3) swap_pos(x, y); 50 | else { 51 | if(op == 1 && x != (inv ? r[y] : l[y])) 52 | move_left(x, inv ? r[y] : y); 53 | else if(op == 2 && x != (inv ? l[y] : r[y])) 54 | move_left(x, inv ? y : r[y]); 55 | } 56 | } 57 | 58 | int main(void) { 59 | int cnt = 0; 60 | while(scanf("%d%d", &n, &m) != EOF) { 61 | init(); 62 | for(int i = 0; i < m; i++) { 63 | // cout << ":::" << i << endl; 64 | int a; scanf("%d", &a); 65 | solve(a); 66 | // print(); 67 | } 68 | long long sum = 0; 69 | if(inv) { 70 | for(int i = l[n+1], cnt = 1; i != 0; i = l[i], cnt++) 71 | if(cnt & 1) sum += i; 72 | } else { 73 | for(int i = r[0], cnt = 1; i != n + 1; i = r[i], cnt++) 74 | if(cnt & 1) sum += i; 75 | } 76 | printf("Case %d: %lld\n", ++cnt, sum); 77 | } 78 | return 0; 79 | } -------------------------------------------------------------------------------- /ch6/uva804.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | struct Trans { 10 | map inputs; 11 | map outputs; 12 | }; 13 | 14 | const int N = 110; 15 | int places[N]; 16 | int nf, n, nt, restf; 17 | Trans tarr[N]; 18 | 19 | bool is_fireable(const Trans& trans) { 20 | for(auto& t : trans.inputs) 21 | if(places[t.first] < t.second) return false; 22 | return true; 23 | } 24 | 25 | void fire(const Trans& trans) { 26 | for(auto& t : trans.inputs) 27 | places[t.first] -= t.second; 28 | for(auto& t : trans.outputs) 29 | places[t.first] += t.second; 30 | } 31 | 32 | bool solve() { 33 | while(restf--) { 34 | bool dead = true; 35 | for(int i = 0; i < nt; i++) 36 | if(is_fireable(tarr[i])) { 37 | fire(tarr[i]); dead = false; break; 38 | } 39 | if(dead) return false; 40 | } 41 | return true; 42 | } 43 | 44 | 45 | int main(void) { 46 | #ifdef LOCAL 47 | freopen("uva804.in", "r", stdin); 48 | freopen("uva804.out", "w", stdout); 49 | #endif 50 | int cnt = 0; 51 | while(scanf("%d", &n), n) { 52 | for(int i = 1; i <= n; i++) 53 | scanf("%d", &places[i]); 54 | scanf("%d", &nt); 55 | for(int i = 0; i < nt; i++) { 56 | int t; 57 | tarr[i] = Trans(); 58 | while(scanf("%d", &t), t) { 59 | if(t < 0) tarr[i].inputs[-t]++; 60 | else tarr[i].outputs[t]++; 61 | } 62 | } 63 | scanf("%d", &nf); restf = nf; 64 | if(solve()) printf("Case %d: still live after %d transitions\n", ++cnt, nf); 65 | else printf("Case %d: dead after %d transitions\n", ++cnt, nf - restf - 1); 66 | printf("Places with tokens:"); 67 | for(int i = 1; i <= n; i++) 68 | if(places[i] > 0) printf(" %d (%d)", i, places[i]); 69 | printf("\n\n"); 70 | } 71 | return 0; 72 | } 73 | 74 | // 这题算是一道大模拟 75 | // 需要一个数组,记录每个place 的token数量 76 | // trans, 需要记录input place 和output place 77 | // 问题在于, trans如何被触发呢? 78 | // 主动轮询,遍历每个trans,判断input place的token是否足够 -------------------------------------------------------------------------------- /ch7/uva818-b.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | const int maxn = 16; 10 | unordered_set g[maxn]; 11 | int comp_cnt, n; 12 | int vis[maxn]; 13 | 14 | // whether the x bit from right is switched on 15 | bool on(int s, int x) { 16 | return s & (1 << x); 17 | } 18 | 19 | // whether the component has cycle 20 | bool dfs_fail(int x, int pre, int s) { 21 | if(vis[x]) return true; 22 | vis[x] = true; 23 | int t = pre == -1 ? 0 : 1; 24 | for(auto i : g[x]) { 25 | if(!on(s,i) && i != pre) { 26 | if(++t > 2 || dfs_fail(i, x, s)) return true; 27 | } 28 | } 29 | return false; 30 | } 31 | 32 | // count the piece be opened 33 | int cal(int s) { 34 | int ans = 0; 35 | for(int i = 0; i < n; i++) 36 | if(on(s, i)) ans++; 37 | return ans; 38 | } 39 | 40 | // check whether each component has cycle and count components 41 | bool valid(int s) { 42 | fill_n(vis, maxn, 0); 43 | int comp_cnt = 0; 44 | int t = cal(s); 45 | for(int i = 0; i < n; i++) { 46 | if(!vis[i] && !on(s, i)) { 47 | if(t < (++comp_cnt - 1) || dfs_fail(i, -1, s)) return false; 48 | } 49 | } 50 | return true; 51 | } 52 | 53 | // enum the open status of pieces 54 | // check whether it will has cycle or some pieces has more than 2 neighbours 55 | // and confirm the opened pieces amount should be sufficient to connect all components 56 | // which means opened pieces >= componets - 1 57 | int solve() { 58 | int ans = maxn; 59 | for(int s = 0; s < (1 << n); s++) { 60 | if(valid(s)) ans = min(cal(s), ans); 61 | } 62 | return ans; 63 | } 64 | 65 | int main(void) { 66 | #ifdef LOCAL 67 | freopen("uva818.out", "w", stdout); 68 | #endif 69 | int cnt = 0; 70 | while(scanf("%d", &n) , n) { 71 | for(int i = 0; i < maxn; i++) g[i].clear(); 72 | int a, b; 73 | while(scanf("%d%d", &a, &b), a != -1) 74 | g[a-1].insert(b-1), g[b-1].insert(a-1); 75 | printf("Set %d: Minimum links to open is %d\n", ++cnt, solve()); 76 | } 77 | return 0; 78 | } -------------------------------------------------------------------------------- /ch6/uva1600.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | typedef pair pii; 9 | #define x first 10 | #define y second 11 | 12 | const int N = 25; 13 | int g[N][N], dist[N][N][N]; 14 | int m, n, k; 15 | int dx[] = {0, 0, -1, 1}, dy[] = {-1, 1, 0, 0}; 16 | 17 | int ID(int r, int c) { 18 | return r * (n + 1) + c; 19 | } 20 | 21 | bool is_unvalid(int a, int b) { 22 | return a < 1 || a > m || b < 1 || b > n; 23 | } 24 | 25 | int solve() { 26 | memset(dist, -1, sizeof(dist)); 27 | queue q; 28 | dist[1][1][0] = 0; 29 | q.push({0, ID(1, 1)}); 30 | while(q.size()) { 31 | auto t = q.front(); q.pop(); 32 | int tx = t.y / (n + 1), ty = t.y % (n + 1), tk = t.x; 33 | if(tx == m && ty == n) return dist[tx][ty][0]; 34 | for(int i = 0; i < 4; i++) { 35 | int a = tx + dx[i], b = ty + dy[i]; 36 | if(is_unvalid(a, b)) continue; 37 | int nk = g[a][b] ? tk + 1 : 0; 38 | if(dist[a][b][nk] < 0 && nk <= k) { 39 | dist[a][b][nk] = dist[tx][ty][tk] + 1; 40 | q.push({nk, ID(a, b)}); 41 | } 42 | } 43 | } 44 | return -1; 45 | } 46 | 47 | int main(void) { 48 | #ifdef LOCAL 49 | freopen("uva1600.in", "r", stdin); 50 | freopen("uva1600.out", "w", stdout); 51 | #endif 52 | int T; scanf("%d", &T); 53 | while(T--) { 54 | scanf("%d%d%d", &m, &n, &k); 55 | for(int i = 1; i <= m; i++) 56 | for(int j = 1; j <= n; j++) 57 | scanf("%d", &g[i][j]); 58 | printf("%d\n", solve()); 59 | } 60 | return 0; 61 | } 62 | 63 | // 最短路问题,有障碍物 64 | // 显然是BFS 65 | // 特定条件,允许连续经过不超过k个障碍物 66 | // 这是好事,因为可能会导致最短路更短 67 | // 但是,要注意:如果连续经过了k个障碍物,下一个如果还是障碍物,就走不动了 68 | // flash: 我想了一下,如果简单记录经过了多少个障碍物,可能有坑 69 | // 解决方案1:记录每个位置是第几个障碍物,如果是0,那么0个;如果是1,那么就是前面连续的1个数+当前的1 70 | // 这样会有什么问题呢? 71 | // 正常的BFS,只需要记录某个位置是否被走过,已经被走过的位置,必不可能用更短的路程到达 72 | // 允许穿越限定数量的障碍物的BFS,对于无障碍物的位置,上述结论依然成立; 73 | // 试想,对于有障碍物的某个位置,可能由于再走一步会超越障碍物的数量,而停止 74 | // 但如果有一条更远的路,到达同一个位置,但是连续通过障碍物更少,就可以通过这个位置,并且走出一条可行路线 75 | // 一个点的最短距离,不仅由位置决定,还由是连续的第几个障碍物决定的 76 | // 通过BFS,某个位置是第x个障碍物的情况,第一次出现时必然是最优情况 77 | // 换言之,点的状态由位置和当前格子是第几个障碍物决定,(r, c, k) 78 | -------------------------------------------------------------------------------- /ch6/uva1103-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | const int M = 210, N = 210; 9 | int m, w, n, grid[M][N], tmp[M][N]; 10 | int dx[] = {0, 0, -1, 1}, dy[] = {1, -1, 0, 0}; 11 | char word[6] = {'W', 'A', 'K', 'J', 'S', 'D'}; 12 | char line[60]; 13 | 14 | void dfs(int sx, int sy) { 15 | if(sx < 0 || sx >= m || sy < 0 || sy >= n) return; 16 | if(grid[sx][sy] != 1) return; 17 | grid[sx][sy] = 0, tmp[sx][sy] = 1; 18 | for(int i = 0; i < 4; i++) dfs(sx + dx[i], sy + dy[i]); 19 | } 20 | 21 | void fill_hole(int sx, int sy) { 22 | if(sx < 0 || sx >= m || sy < 0 || sy >= n) return; 23 | if(tmp[sx][sy] != 0) return; 24 | tmp[sx][sy] = 1; 25 | for(int i = 0; i < 4; i++) fill_hole(sx + dx[i], sy + dy[i]); 26 | } 27 | 28 | int count_hole() { 29 | int ans = 0; 30 | for(int i = 0; i < m; i++) 31 | for(int j = 0; j < n; j++) 32 | if(tmp[i][j] == 0) fill_hole(i, j), ans++; 33 | return ans - 1; 34 | } 35 | 36 | void read_pic() { 37 | memset(grid, 0, sizeof(grid)); 38 | for(int i = 1; i <= m; i++) { 39 | scanf("%s", line); 40 | for(int j = 0; j < w; j++) { 41 | char ch = line[j]; 42 | int num; 43 | if(isdigit(ch)) num = ch - '0'; 44 | else num = 10 + (ch - 'a'); 45 | for(int k = 3; k >= 0; k--) { 46 | grid[i][1 + 4 * j + k] = num & 1; 47 | num >>= 1; 48 | } 49 | } 50 | } 51 | n = 4 * w; 52 | m += 2, n += 2; 53 | } 54 | 55 | int main(void) { 56 | int cnt = 0; 57 | while(scanf("%d%d\n", &m, &w) != EOF, m) { 58 | read_pic(); 59 | 60 | vector v; 61 | for(int i = 0; i < m; i++) 62 | for(int j = 0; j < n; j++) { 63 | if(grid[i][j] == 1) { 64 | memset(tmp, 0, sizeof tmp); 65 | dfs(i, j); 66 | int hole = count_hole(); 67 | v.push_back(word[hole]); 68 | } 69 | } 70 | sort(v.begin(), v.end()); 71 | printf("Case %d: ", ++cnt); 72 | for(auto& ch : v) putchar(ch); 73 | puts(""); 74 | } 75 | return 0; 76 | } -------------------------------------------------------------------------------- /ch6/uva10129.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int p[26], deg[26]; 9 | bool used[26]; 10 | char word[1010]; 11 | 12 | char find(int x) { 13 | if(p[x] != x) p[x] = find(p[x]); 14 | return p[x]; 15 | } 16 | 17 | void union_set(int a, int b) { 18 | p[find(a)] = p[find(b)]; 19 | } 20 | 21 | void init() { 22 | for(int i = 0; i < 26; i++) p[i] = i; 23 | memset(used, 0, sizeof(used)); 24 | memset(deg, 0, sizeof(deg)); 25 | } 26 | 27 | int main(void) { 28 | int T; scanf("%d", &T); 29 | while(T--) { 30 | int n; scanf("%d", &n); 31 | init(); 32 | int cnt = 26; 33 | for(int i = 0; i < n; i++) { 34 | scanf("%s", word); 35 | int size = strlen(word); 36 | int ch1 = word[0] - 'a', ch2 = word[size - 1] - 'a'; 37 | if(find(ch1) != find(ch2)) cnt--, union_set(ch1, ch2); 38 | used[ch1] = used[ch2] = true; 39 | deg[ch1]--, deg[ch2]++; 40 | } 41 | for(int i = 0; i < 26; i++) 42 | if(!used[i]) cnt--; 43 | // printf("cnt : %d\n", cnt); 44 | vector v; 45 | for(int i = 0; i < 26; i++) 46 | if(deg[i] != 0) v.push_back(deg[i]); 47 | sort(v.begin(), v.end()); 48 | // for(int i = 0; i < v.size(); i++) 49 | // printf("%d\n", v[i]); 50 | bool flag = false; 51 | if(v.size() == 0) flag = true; 52 | if(v.size() == 2 && v[0] == -1 && v[1] == 1) flag = true; 53 | if(cnt != 1) flag = false; 54 | if(flag) puts("Ordering is possible."); 55 | else puts("The door cannot be opened."); 56 | } 57 | return 0; 58 | } 59 | 60 | // 这道题,要求将全部单词首尾相接 61 | // 首先,全部相接 ,说明这些词共同组成一个连通分量 62 | // 第二,要确保整个连通分量,单词之间在数量上,按照首尾相接的要求一一对应 63 | 64 | // 1. 统计连通分量数量,可以用DFS或者并查集 65 | // 2. 这是一个经典的欧拉道路问题,也叫“一笔画”, 66 | // 在有向图中,它的充分条件是: 67 | // 1. 忽略边的方向时,图是连通的 68 | // 2. 所有点出入度相等,或者有且只有2个点的出度不等于入度,一个出度比入度大1,另一个出度比入度小1 69 | 70 | // 方案1:并查集 71 | // 将26个字母看作一个点,单词看作有向边 72 | // 初始有26个连通分量 73 | // union被边连接的点 74 | // 最终连通分量数量 = 连通分量数量 - 孤点数量 75 | 76 | // 构建并查集的过程中,记录每个点的出度和入度 77 | // 最后,统计出入度之差非0的点的数量 78 | 79 | // 方案2:DFS 80 | // 统计连通分量:DFS一次任意点,判断是否存在未被遍历的点 81 | // 统计出入度:构建图时,统计出入度 -------------------------------------------------------------------------------- /arrayandstring/uva232-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | typedef pair PIS; 9 | 10 | const int N = 15; 11 | int r, c; 12 | char grid[N][N]; 13 | int number[N][N]; 14 | 15 | bool read_puzzle() { 16 | scanf("%d", &r); 17 | if(r == 0) return false; 18 | scanf("%d\n", &c); 19 | for(int i = 0; i < r; i++) { 20 | scanf("%s", grid[i]); 21 | } 22 | return true; 23 | } 24 | 25 | bool check_idx(int x, int y) { 26 | return x >= 0 && x <= r && y >= 0 && y <= c; 27 | } 28 | 29 | void numbering() { 30 | int num = 0; 31 | for(int i = 0; i < r; i++) { 32 | for(int j = 0; j < c; j++) { 33 | if(grid[i][j] == '*') continue; 34 | int ax = i - 1, ay = j; 35 | int lx = i, ly = j - 1; 36 | if(!check_idx(ax, ay) || grid[ax][ay] == '*' 37 | || !check_idx(lx, ly) || grid[lx][ly] == '*') 38 | number[i][j] = ++num; 39 | } 40 | } 41 | } 42 | 43 | void solve() { 44 | printf("Across\n"); 45 | for(int i = 0; i < r; i++) { 46 | for(int j = 0; j < c; ) { 47 | while(j < c && grid[i][j] == '*') j++; 48 | if(j >= c) break; 49 | int num = number[i][j]; 50 | string t; 51 | while(j < c && grid[i][j] != '*') t += grid[i][j++]; 52 | printf("%3d.%s\n", num, t.c_str()); 53 | } 54 | } 55 | vector v; 56 | for(int j = 0; j < c; j++) { 57 | for(int i = 0; i < r; ) { 58 | while(i < r && grid[i][j] == '*') i++; 59 | if(i >= r) break; 60 | string t; 61 | int num = number[i][j]; 62 | while(i < r && grid[i][j] != '*') t += grid[i++][j]; 63 | v.push_back({num, t}); 64 | } 65 | } 66 | sort(v.begin(), v.end()); 67 | printf("Down\n"); 68 | for(int i = 0; i < v.size(); i++) { 69 | printf("%3d.%s\n", v[i].first, v[i].second.c_str()); 70 | } 71 | } 72 | 73 | int main() { 74 | for(int i = 1; ; i++) { 75 | if(!read_puzzle()) break; 76 | memset(number, 0, sizeof number); 77 | numbering(); 78 | if(i != 1) puts(""); 79 | printf("puzzle #%d:\n", i); 80 | solve(); 81 | } 82 | return 0; 83 | } -------------------------------------------------------------------------------- /ch7/uva1343.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | // 0, 1 9 | // 2, 3 10 | // 4 , 5, 6, 7, 8, 9,10 11 | // 11, ,12 12 | // 13,14,15,16,17,18,19 13 | // 20 21 14 | // 22 23 15 | 16 | int bd[24]; 17 | int map[8][7] = { 18 | {0, 2, 6, 11, 15, 20, 22}, 19 | {1, 3, 8, 12, 17, 21, 23}, 20 | {10, 9, 8, 7, 6, 5, 4}, 21 | {19, 18, 17, 16, 15, 14, 13} 22 | }; 23 | 24 | int center[8] = {6, 7, 8, 11, 12, 15, 16, 17}; 25 | 26 | const int rev[8] = {5, 4, 7, 6, 1, 0, 3, 2}; 27 | 28 | vector ans(1000); 29 | 30 | void move(int i) { 31 | int t = bd[map[i][0]]; 32 | for(int j = 1; j < 7; j++) bd[map[i][j-1]] = bd[map[i][j]]; 33 | bd[map[i][6]] = t; 34 | } 35 | 36 | int diff(int x) { 37 | int ans = 0; 38 | for(int i = 0; i < 8; i++) 39 | if(bd[center[i]] != x) ans++; 40 | return ans; 41 | } 42 | 43 | int h() { 44 | return min(diff(1), min(diff(2), diff(3))); 45 | } 46 | 47 | bool found() { 48 | for(int i = 0; i < 8; i++) 49 | if (bd[center[i]] != bd[center[0]]) return false; 50 | return true; 51 | } 52 | 53 | bool dfs(int d, int maxd) { 54 | if(found()) { 55 | for(int i = 0; i < d; i++) putchar(ans[i]); 56 | printf("\n"); 57 | return true; 58 | } 59 | if(d + h() > maxd) return false; 60 | for(int i = 0; i < 8; i++) { 61 | move(i); 62 | if(ans.size() < d + 1) ans.push_back('A' + i); 63 | else ans[d] = 'A' + i; 64 | if(dfs(d + 1, maxd)) return true; 65 | move(rev[i]); 66 | } 67 | return false; 68 | } 69 | 70 | int main(void) { 71 | #ifdef LOCAL 72 | freopen("uva1343.in", "r", stdin); 73 | freopen("uva1343.out", "w", stdout); 74 | #endif 75 | for(int i = 4; i < 8; i++) 76 | for(int j = 0; j < 7; j++) 77 | map[i][j] = map[rev[i]][6-j]; 78 | 79 | while(scanf("%d", &bd[0]), bd[0]) { 80 | for(int i = 1; i < 24; i++) 81 | scanf("%d", &bd[i]); 82 | 83 | if(found()) { 84 | printf("No moves needed\n"); 85 | } else { 86 | for(int maxd = 1; ; maxd++) 87 | if(dfs(0, maxd)) break; 88 | } 89 | printf("%d\n", bd[6]); 90 | } 91 | return 0; 92 | } 93 | 94 | // 这题,对于这种异形状态的建模是重点,利用了映射的思想 -------------------------------------------------------------------------------- /ch6/uva122-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | // 动态创建节点思路 8 | struct Node { 9 | bool has_val; 10 | int val; 11 | Node *left, *right; 12 | Node() : has_val(false), left(NULL), right(NULL) {} 13 | }; 14 | 15 | Node *root; 16 | bool failed; 17 | 18 | bool add_node(const string& path, int val) { 19 | auto u = root; 20 | for(int i = 0; i < path.size(); i++) { 21 | char ch = path[i]; 22 | if(ch == 'L') { 23 | if(!u->left) u->left = new Node(); 24 | u = u->left; 25 | } else if(ch == 'R') { 26 | if(!u->right) u->right = new Node(); 27 | u = u->right; 28 | } 29 | } 30 | if(u->has_val) return false; 31 | u->val = val; 32 | u->has_val = true; 33 | return true; 34 | } 35 | 36 | bool read_tree() { 37 | root = new Node(); 38 | for(;;) { 39 | char ch; 40 | while(ch = getchar(), isspace(ch)); 41 | if(ch == EOF) return false; 42 | ch = getchar(); 43 | if(ch == ')') break; 44 | int val = ch - '0'; 45 | while(ch = getchar(), ch != ',') 46 | val = val * 10 + (ch - '0'); 47 | string path; 48 | while(ch = getchar(), ch != ')') 49 | path += ch; 50 | if(!add_node(path, val)) failed = true; 51 | } 52 | return true; 53 | } 54 | 55 | void remove_tree(Node *u) { 56 | if(!u) return; 57 | remove_tree(u->left); 58 | remove_tree(u->right); 59 | delete u; 60 | } 61 | 62 | bool bfs(Node* root) { 63 | if(failed) return false; 64 | queue q; 65 | q.push(root); 66 | vector ans; 67 | while(q.size()) { 68 | int len = q.size(); 69 | for(int i = 0; i < len; i++) { 70 | auto u = q.front(); q.pop(); 71 | if(!u->has_val) return false; 72 | ans.push_back(u->val); 73 | if(u->left) q.push(u->left); 74 | if(u->right) q.push(u->right); 75 | } 76 | } 77 | for(int i = 0; i < ans.size(); i++) 78 | printf(i > 0 ? " %d" : "%d", ans[i]); 79 | puts(""); 80 | return true; 81 | } 82 | 83 | int main(void) { 84 | while(read_tree()) { 85 | if(!bfs(root)) puts("not complete"); 86 | remove_tree(root); 87 | failed = false; 88 | } 89 | return 0; 90 | } -------------------------------------------------------------------------------- /ch7/uva140.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | bool g[10][10]; 9 | int nnode, ans; 10 | char names[10]; 11 | map nums; 12 | string path, fpath; 13 | bool used[10]; 14 | 15 | // 依然是编号的思想,很重要很重要 16 | int NO(char c) { 17 | if(nums.count(c)) return nums[c]; 18 | names[nnode] = c; 19 | nums[c] = nnode; 20 | return nnode++; 21 | } 22 | 23 | bool handle_input() { 24 | nums.clear(); 25 | nnode = 0; 26 | memset(g, 0, sizeof(g)); 27 | int ch; 28 | while(ch = getchar(), !isalpha(ch) && ch != '#'); 29 | ; 30 | if(ch == '#') return false; 31 | do { 32 | int no = NO(ch); 33 | getchar(); 34 | while((ch = getchar()) != ';' && !isspace(ch)) { 35 | int to = NO(ch); 36 | g[no][to] = g[to][no] = true; 37 | } 38 | if(ch == ';') ch = getchar(); 39 | } while(isalpha(ch)); 40 | return true; 41 | } 42 | 43 | void dfs(int x, int pre) { 44 | if(used[x]) return; 45 | int t = 0; 46 | int n = path.size(); 47 | for(int j = 0; j < n; j++) { 48 | int y = NO(path[j]); 49 | if(g[x][y] && n - j > t) 50 | t = n - j; 51 | } 52 | if(t > ans) return; 53 | 54 | if(t > pre) pre = t; 55 | used[x] = true; 56 | path.push_back(names[x]); 57 | if(path.size() == nnode) { 58 | if(pre < ans) ans = pre, fpath = path; 59 | if(pre == ans && path < fpath) fpath = path; 60 | } 61 | // 如果是等待再下一次递归再记录path,会导致不必要的递归 62 | for(int i = 0; path.size() < nnode && i < nnode; i++) 63 | dfs(i, pre); 64 | used[x] = false; 65 | path.pop_back(); 66 | } 67 | 68 | int main(void) { 69 | #ifdef LOCAL 70 | freopen("uva140.in", "r", stdin); 71 | freopen("uva140.out", "w", stdout); 72 | #endif 73 | while(handle_input()) { 74 | ans = nnode; 75 | memset(used, 0, sizeof(used)); 76 | path.clear(); 77 | for(int i = 0; i < nnode; i++) 78 | dfs(i, 0); 79 | for(int i = 0; i < nnode; i++) 80 | printf(i > 0 ? " %c" : "%c", fpath[i]); 81 | printf(" -> %d\n", ans); 82 | } 83 | return 0; 84 | } 85 | 86 | // DFS穷举(不是哈密顿路径), 计算并比较bandwith of ordering, 保存最小的 87 | // 剪枝条件:1. 当前bandwith已经等于min val 2. 当前节点的未访问节点数 + 当前bandwith = min val 88 | // 给每个节点一个编号 89 | // 稀疏图,用邻接链表表示 90 | // 枚举所有的节点编号为起点,遍历记录path,中途剪枝,最后记录 -------------------------------------------------------------------------------- /ch4/uva201.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | // n * n点矩阵 9 | // m条边 10 | // 枚举每个点,从0 ... n - 1 11 | // 以每个点为左上角,枚举边长 1 ... min(n - 1 - x, n - 1 - y) 12 | // 对于每个左上角(x, y)和边长len确定的正方形,判断是否所有边都存在 13 | 14 | const int N = 15; 15 | bool st[N * N][N * N]; 16 | int n, m; 17 | 18 | int idx(int x, int y) { 19 | return x * n + y; 20 | } 21 | 22 | bool check_edge(int x, int y, int len, bool is_x_axis) { 23 | int fx = x, fy = y, tx = x + (is_x_axis ? 0 : 1), ty = y + (is_x_axis ? 1 : 0); 24 | for(int i = 0; i < len; i++) { 25 | if(!st[idx(fx, fy)][idx(tx,ty)]) return false; 26 | if(is_x_axis) fy++, ty++; 27 | else fx++, tx++; 28 | } 29 | return true; 30 | } 31 | 32 | bool check(int x, int y, int len) { 33 | // up, left, right, down 34 | int fx = x, fy = y; 35 | if(!check_edge(fx, fy, len, true)) return false; 36 | if(!check_edge(fx, fy, len, false)) return false; 37 | fx = x, fy = y + len; 38 | if(!check_edge(fx, fy, len, false)) return false; 39 | fx = x + len, fy = y; 40 | if(!check_edge(fx, fy, len, true)) return false; 41 | return true; 42 | } 43 | 44 | void solve(int cnt) { 45 | map map; 46 | for(int i = 1; i <= n; i++) { 47 | for(int j = 1; j <= n; j++) { 48 | for(int len = 1; len <= min(n - i, n - j); len++) 49 | if(check(i, j, len)) map[len]++; 50 | } 51 | } 52 | if(cnt != 1) printf("\n**********************************\n\n"); 53 | printf("Problem #%d\n\n", cnt); 54 | if(!map.size()) printf("No completed squares can be found.\n"); 55 | for(auto p : map) { 56 | printf("%d square (s) of size %d\n", p.second, p.first); 57 | } 58 | } 59 | 60 | int main(void) { 61 | int cnt = 1; 62 | while(scanf("%d%d", &n, &m) != EOF) { 63 | memset(st, 0, sizeof st); 64 | for(int k = 0; k < m; k++) { 65 | char type; 66 | int i, j; 67 | cin >> type >> i >> j; 68 | if(type == 'H') { 69 | int a = idx(i, j), b = idx(i, j + 1); 70 | st[a][b] = st[b][a] = true; 71 | } else if(type == 'V') { 72 | int a = idx(j, i), b = idx(j + 1, i); 73 | st[a][b] = st[b][a] = true; 74 | } 75 | } 76 | solve(cnt); 77 | cnt++; 78 | } 79 | return 0; 80 | } -------------------------------------------------------------------------------- /ch6/uva210-c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int a[26], pc[11]; 9 | bool locked; 10 | int tunit; 11 | int n, inst_time[5]; 12 | queue bq; 13 | deque rq; 14 | string progs[11][30]; 15 | 16 | void run() { 17 | for(int i = 1; i <= n; i++) { 18 | string t; 19 | int cnt = 0; 20 | do { 21 | t.clear(); 22 | int ch; 23 | while(ch = getchar(), ch == '\n' || ch == '\r'); 24 | t += ch; 25 | while(ch = getchar(), ch != '\n' && ch != '\r') 26 | t += ch; 27 | // cout << "::::" << t << endl; 28 | progs[i][cnt++] = t; 29 | } while(t != "end"); 30 | } 31 | for(int i = 1; i <= n; i++) rq.push_back(i); 32 | memset(a, 0, sizeof a); 33 | memset(pc, 0, sizeof pc); 34 | locked = false; 35 | 36 | while(rq.size()) { 37 | int pid = rq.front(); rq.pop_front(); 38 | bool flag = true; 39 | for(int i = 0; i < tunit; ) { 40 | string p = progs[pid][pc[pid]]; 41 | int ch = p[2]; 42 | if(ch == '=') { 43 | a[p[0] - 'a'] = isdigit(p[5]) ? (p[4] - '0') * 10 + p[5] - '0' : p[4] - '0'; 44 | i += inst_time[0]; 45 | } else if(ch == 'i') { 46 | printf("%d: %d\n", pid, a[p[6] - 'a']); 47 | i += inst_time[1]; 48 | } else if(ch == 'c') { 49 | if(locked) { 50 | bq.push(pid), flag = false; break; 51 | } else locked = true; 52 | i += inst_time[2]; 53 | } else if(ch == 'l') { 54 | locked = false; 55 | if(bq.size()) rq.push_front(bq.front()), bq.pop(); 56 | i += inst_time[3]; 57 | } else if(ch == 'd') { 58 | i += inst_time[4]; 59 | pc[pid]++; 60 | flag = false; 61 | break; 62 | } 63 | pc[pid]++; 64 | } 65 | if(flag) rq.push_back(pid); 66 | } 67 | } 68 | 69 | int main(void) { 70 | int T; scanf("%d", &T); 71 | for(int i = 0; i < T; i++) { 72 | if(i > 0) puts(""); 73 | scanf("%d", &n); 74 | for(int i = 0; i < 5; i++) scanf("%d", &inst_time[i]); 75 | scanf("%d", &tunit); 76 | for(char ch = getchar(); ch != '\n'; ch = getchar()); 77 | run(); 78 | } 79 | return 0; 80 | } -------------------------------------------------------------------------------- /arrayandstring/uva232-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | typedef pair PIS; 9 | 10 | const int N = 15; 11 | int r, c; 12 | char grid[N][N]; 13 | int number[N][N]; 14 | 15 | bool verify(char ch) { 16 | return ch == '*' || isalpha(ch); 17 | } 18 | 19 | bool read_puzzle() { 20 | scanf("%d", &r); 21 | if(r == 0) return false; 22 | scanf("%d\n", &c); 23 | for(int i = 0; i < r; i++) 24 | for(int j = 0; j < c; j++) { 25 | char ch; 26 | while(!verify(ch = getchar())); 27 | grid[i][j] = ch; 28 | } 29 | return true; 30 | } 31 | 32 | bool check_idx(int x, int y) { 33 | return x >= 0 && x <= r && y >= 0 && y <= c; 34 | } 35 | 36 | void numbering() { 37 | int num = 0; 38 | for(int i = 0; i < r; i++) { 39 | for(int j = 0; j < c; j++) { 40 | if(grid[i][j] == '*') continue; 41 | int ax = i - 1, ay = j; 42 | int lx = i, ly = j - 1; 43 | if(!check_idx(ax, ay) || grid[ax][ay] == '*' 44 | || !check_idx(lx, ly) || grid[lx][ly] == '*') 45 | number[i][j] = ++num; 46 | } 47 | } 48 | } 49 | 50 | void solve() { 51 | printf("Across\n"); 52 | for(int i = 0; i < r; i++) { 53 | for(int j = 0; j < c; ) { 54 | while(j < c && grid[i][j] == '*') j++; 55 | if(j >= c) break; 56 | int num = number[i][j]; 57 | string t; 58 | while(j < c && grid[i][j] != '*') t += grid[i][j++]; 59 | printf("%3d.%s\n", num, t.c_str()); 60 | } 61 | } 62 | vector v; 63 | for(int j = 0; j < c; j++) { 64 | for(int i = 0; i < r; ) { 65 | while(i < r && grid[i][j] == '*') i++; 66 | if(i >= r) break; 67 | string t; 68 | int num = number[i][j]; 69 | while(i < r && grid[i][j] != '*') t += grid[i++][j]; 70 | v.push_back({num, t}); 71 | } 72 | } 73 | sort(v.begin(), v.end()); 74 | printf("Down\n"); 75 | for(int i = 0; i < v.size(); i++) { 76 | printf("%3d.%s\n", v[i].first, v[i].second.c_str()); 77 | } 78 | } 79 | 80 | int main() { 81 | for(int i = 1; ; i++) { 82 | if(!read_puzzle()) break; 83 | memset(number, 0, sizeof number); 84 | numbering(); 85 | if(i != 1) puts(""); 86 | printf("puzzle #%d:\n", i); 87 | solve(); 88 | } 89 | return 0; 90 | } -------------------------------------------------------------------------------- /ch6/uva210.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | 9 | // 模拟不超过10个程序,在单CPU系统的并发执行 10 | // 程序可能的2种状态:running, ready 11 | // running中的程序会被分配quantum,即允许执行的time unit 12 | // 13 | // 单个程序不超过25条指令,不包括最后的end指令 14 | // 有5种指令 15 | // var是小写字母,const是小于100的unsigned 16 | // 系统中只有26种变量,并且在程序之间共享,变量的初始值都是0 17 | // ready queue, blocked queue 18 | int a[26]; 19 | bool locked; 20 | int tunit; 21 | int n, inst_time[5]; 22 | queue bq; 23 | deque rq; 24 | 25 | // getline和sstream都可以优化,特别是sstream 26 | void run() { 27 | queue progs[11]; 28 | for(int i = 1; i <= n; i++) { 29 | string t; 30 | do getline(cin, t), progs[i].push(t); while(t != "end"); 31 | } 32 | for(int i = 1; i <= n; i++) rq.push_back(i); 33 | memset(a, 0, sizeof a); 34 | locked = false; 35 | 36 | while(rq.size()) { 37 | int pid = rq.front(); rq.pop_front(); 38 | bool flag = true; 39 | for(int i = 0; i < tunit; ) { 40 | stringstream ss(progs[pid].front()); 41 | string cmd; ss >> cmd; 42 | // cout << "inst : " << cmd << endl; 43 | if(cmd == "print") { 44 | char ch; ss >> ch; 45 | printf("%d: %d\n", pid, a[ch - 'a']); 46 | i += inst_time[1]; 47 | } else if(cmd == "lock") { 48 | if(locked) { 49 | bq.push(pid), flag = false; break; 50 | } else locked = true; 51 | i += inst_time[2]; 52 | } else if(cmd == "unlock") { 53 | locked = false; 54 | if(bq.size()) rq.push_front(bq.front()), bq.pop(); 55 | i += inst_time[3]; 56 | } else if(cmd == "end") { 57 | i += inst_time[4]; 58 | progs[pid].pop(); 59 | flag = false; 60 | break; 61 | } else { 62 | string t; ss >> t; 63 | int val; ss >> val; 64 | a[cmd[0] - 'a'] = val; 65 | i += inst_time[0]; 66 | } 67 | progs[pid].pop(); 68 | } 69 | if(flag) rq.push_back(pid); 70 | } 71 | } 72 | 73 | int main(void) { 74 | int T; scanf("%d", &T); 75 | for(int i = 0; i < T; i++) { 76 | if(i > 0) puts(""); 77 | scanf("%d", &n); 78 | for(int i = 0; i < 5; i++) scanf("%d", &inst_time[i]); 79 | scanf("%d", &tunit); 80 | for(char ch = getchar(); ch != '\n'; ch = getchar()); 81 | run(); 82 | } 83 | return 0; 84 | } -------------------------------------------------------------------------------- /ch6/uva210-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int a[26], pc[11]; 9 | bool locked; 10 | int tunit; 11 | int n, inst_time[5]; 12 | queue bq; 13 | deque rq; 14 | string progs[11][30]; 15 | 16 | void run() { 17 | for(int i = 1; i <= n; i++) { 18 | string t; 19 | int cnt = 0; 20 | do { 21 | t.clear(); 22 | int ch; 23 | while(ch = getchar(), ch == '\n' || ch == '\r'); 24 | t += ch; 25 | while(ch = getchar(), ch != '\n' && ch != '\r') 26 | t += ch; 27 | // cout << "::::" << t << endl; 28 | progs[i][cnt++] = t; 29 | } while(t != "end"); 30 | } 31 | for(int i = 1; i <= n; i++) rq.push_back(i); 32 | memset(a, 0, sizeof a); 33 | memset(pc, 0, sizeof pc); 34 | locked = false; 35 | 36 | while(rq.size()) { 37 | int pid = rq.front(); rq.pop_front(); 38 | bool flag = true; 39 | for(int i = 0; i < tunit; ) { 40 | stringstream ss(progs[pid][pc[pid]]); 41 | string cmd; ss >> cmd; 42 | // cout << "inst : " << cmd << endl; 43 | if(cmd == "print") { 44 | char ch; ss >> ch; 45 | printf("%d: %d\n", pid, a[ch - 'a']); 46 | i += inst_time[1]; 47 | } else if(cmd == "lock") { 48 | if(locked) { 49 | bq.push(pid), flag = false; break; 50 | } else locked = true; 51 | i += inst_time[2]; 52 | } else if(cmd == "unlock") { 53 | locked = false; 54 | if(bq.size()) rq.push_front(bq.front()), bq.pop(); 55 | i += inst_time[3]; 56 | } else if(cmd == "end") { 57 | i += inst_time[4]; 58 | pc[pid]++; 59 | flag = false; 60 | break; 61 | } else { 62 | string t; ss >> t; 63 | int val; ss >> val; 64 | a[cmd[0] - 'a'] = val; 65 | i += inst_time[0]; 66 | } 67 | pc[pid]++; 68 | } 69 | if(flag) rq.push_back(pid); 70 | } 71 | } 72 | 73 | int main(void) { 74 | int T; scanf("%d", &T); 75 | for(int i = 0; i < T; i++) { 76 | if(i > 0) puts(""); 77 | scanf("%d", &n); 78 | for(int i = 0; i < 5; i++) scanf("%d", &inst_time[i]); 79 | scanf("%d", &tunit); 80 | for(char ch = getchar(); ch != '\n'; ch = getchar()); 81 | run(); 82 | } 83 | return 0; 84 | } -------------------------------------------------------------------------------- /ch5/uva230.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | typedef pair pss; 11 | // 用链表,达到常量时间的插入和删除 12 | list shelf; 13 | // idx即字符串id 14 | vector v; 15 | // 临时保存归还但未返架的图书 16 | vector returned; 17 | // 根据字符串查id 18 | unordered_map map; 19 | 20 | bool read_title(string& p) { 21 | int ch; 22 | while(ch = getchar(), ch != '\"' || ch != 'E') { 23 | if(ch == 'E') {getchar(), getchar(); return false;} 24 | else if(ch == '\"') break; 25 | } 26 | while(ch = getchar(), ch != '\"') 27 | p += ch; 28 | return true; 29 | } 30 | 31 | bool read_book() { 32 | int ch; 33 | string title; 34 | if(!read_title(title)) return false; 35 | string aut_name; 36 | while(ch = getchar(), ch != 'y'); 37 | while(ch = getchar(), !isalpha(ch)); 38 | aut_name += ch; 39 | while(ch = getchar(), ch != '\n' && ch != '\r') 40 | aut_name += ch; 41 | // cout << title << ":" << aut_name << endl; 42 | v.push_back({aut_name, title}); 43 | return true; 44 | } 45 | 46 | void init_shelf() { 47 | sort(v.begin(), v.end()); 48 | for(int i = 0; i < v.size(); i++) { 49 | string title = v[i].second; 50 | shelf.push_back(i); 51 | map[title] = i; 52 | } 53 | } 54 | 55 | void borrow(const string& title) { 56 | int id = map[title]; 57 | auto itr = find(shelf.begin(), shelf.end(), id); 58 | shelf.erase(itr); 59 | } 60 | 61 | void ret(const string& title) { 62 | returned.push_back(map[title]); 63 | } 64 | 65 | void shelve(int id) { 66 | auto itr = upper_bound(shelf.begin(), shelf.end(), id); 67 | if(itr == shelf.begin()) { 68 | printf("Put \"%s\" first\n", v[id].second.c_str()); 69 | shelf.insert(itr, id); 70 | } else { 71 | printf("Put \"%s\" after \"%s\"\n", v[id].second.c_str(), v[*(--itr)].second.c_str()); 72 | shelf.insert(++itr, id); 73 | } 74 | } 75 | 76 | void shelve_all() { 77 | sort(returned.begin(), returned.end()); 78 | for(int i = 0; i < returned.size(); i++) 79 | shelve(returned[i]); 80 | returned.clear(); 81 | puts("END"); 82 | } 83 | 84 | // pss肯定要用来排序的,这个毫无疑问 85 | int main(void) { 86 | while(read_book()); 87 | init_shelf(); 88 | char cmd[10]; 89 | for(;;) { 90 | memset(cmd, 0, sizeof cmd); 91 | scanf("%s", cmd); 92 | if(cmd[0] == 'E') break; 93 | string p; 94 | if(cmd[0] == 'B') read_title(p), borrow(p); 95 | else if(cmd[0] == 'R') read_title(p), ret(p); 96 | else if(cmd[0] == 'S') shelve_all(); 97 | } 98 | return 0; 99 | } -------------------------------------------------------------------------------- /ch7/uva1603.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int n; 9 | 10 | bool is_complete(unordered_set& set, int from, int step, int n) { 11 | for(int i = from; i < from + n; i += step) 12 | if(set.count(i)) return false; 13 | return true; 14 | } 15 | 16 | bool has_square(unordered_set& set, int n) { 17 | for(int r = 0; r < n; r++) { 18 | for(int c = 1; c <= n; c++) { 19 | int x = r * (2*n+1) + c; 20 | int mlen = max(n-x%(2*n+1)+1, n-(x+n)/(2*n+1)); 21 | for(int k = 1; k <= mlen; k++) { 22 | if(is_complete(set, x, 1, k) 23 | && is_complete(set, x + n, 2*n+1, k) 24 | && is_complete(set, x + k + n, 2*n+1, k) 25 | && is_complete(set, x + k*(2*n+1), 1, k)) 26 | return true; 27 | } 28 | } 29 | } 30 | return false; 31 | } 32 | 33 | bool dfs(int d, int maxd, int s, vector& v, unordered_set& set) { 34 | if(d == maxd) { 35 | if(has_square(set, n)) return false; 36 | else { 37 | for(auto t : set) cout << t << ' '; 38 | cout << endl; 39 | printf("%d\n", d); 40 | return true; 41 | } 42 | } 43 | for(int i = s; i < v.size(); i++) { 44 | set.insert(v[i]); 45 | if(dfs(d+1, maxd, i+1, v, set)) return true; 46 | set.erase(v[i]); 47 | } 48 | return false; 49 | } 50 | 51 | int main(void) { 52 | int T; scanf("%d", &T); 53 | while(T--) { 54 | int k; 55 | scanf("%d%d", &n, &k); 56 | unordered_set set; 57 | for(int i = 0; i < k; i++) { 58 | int t; scanf("%d", &t); 59 | set.insert(t); 60 | } 61 | vector v; 62 | for(int i = 1; i <= 2*n*(n+1); i++) 63 | if(!set.count(i)) v.push_back(i); 64 | for(int maxd = 0; ; maxd++) 65 | if(dfs(0, maxd, 0, v, set)) break; 66 | } 67 | return 0; 68 | } 69 | 70 | // 枚举要拆除的边,最后验证是否存在正方形 71 | // 边长为n的格子,竖的n(n+1),横的n(n+1), 总共2n(n+1), 编号从1到2n(n+1) 72 | // 通过已经被拆除的边集合,判断是否存在正方形 73 | // 如何判断是否存在square? 74 | // 枚举所有正方形,逐个检查 75 | // 枚举所有正方形第一行的第一条边 76 | // 第0行的有1...n 77 | // 第1行n+(n+1)+1...2n+(n+1) 78 | // 第2行2n+2(n+1)+1...3n+2(n+1) 79 | // 以此类推 80 | // 对于每条边,我们枚举所有可能的大小,去检查 81 | // 对于长度为k的正方形 82 | // 横的上边从左往右+1,竖的边从上往下+(2n+1) 83 | // 横的下边从左往右+1 84 | // 左竖边的第一条边,是上横第一条边+n 85 | // 右竖边的第一条边,是上横第一条边+k-1+n+1=+k+n 86 | // 下横边的第一条边,是上横第一条边的k(2n+1) 87 | // 88 | // 对于边x,它所代表的正方形,边长范围是多少呢? 89 | // 取决于它是某一行的第几条边。只需要x % (n+n+1),横的最大长度是n-x%(2n+1)+1 90 | // 竖的最大长度,首先左竖边的编号是x+n, 它处于第几行呢?(x+n)/(2n+1), 竖的最大长度是n-(x+n)/(2n+1) 91 | // 所以边长范围是[1..max(n-x%(2n+1)+1, n-(x+n)/(2n+1))] 92 | // 这个版本暴力超时了,先放着 -------------------------------------------------------------------------------- /ch6/uva122-c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | // 动态创建节点思路 8 | struct Node { 9 | bool has_val; 10 | int val; 11 | Node *left, *right; 12 | Node() : has_val(false), left(NULL), right(NULL) {} 13 | }; 14 | 15 | Node *root; 16 | bool failed; 17 | queue freenodes; 18 | Node nodes[260]; 19 | // 内存池技术 20 | void init() { 21 | for(int i = 0; i < (sizeof(nodes)) / (sizeof(Node)); i++) 22 | freenodes.push(&nodes[i]); 23 | } 24 | 25 | auto newnode() -> Node* { 26 | auto ans = freenodes.front(); freenodes.pop(); 27 | ans->left = ans->right = NULL, ans->has_val = false; 28 | return ans; 29 | } 30 | 31 | void remove_tree(Node *u) { 32 | if(!u) return; 33 | remove_tree(u->left); 34 | remove_tree(u->right); 35 | freenodes.push(u); 36 | } 37 | 38 | bool add_node(const string& path, int val) { 39 | auto u = root; 40 | for(int i = 0; i < path.size(); i++) { 41 | char ch = path[i]; 42 | if(ch == 'L') { 43 | if(!u->left) u->left = newnode(); 44 | u = u->left; 45 | } else if(ch == 'R') { 46 | if(!u->right) u->right = newnode(); 47 | u = u->right; 48 | } 49 | } 50 | if(u->has_val) return false; 51 | u->val = val; 52 | u->has_val = true; 53 | return true; 54 | } 55 | 56 | bool read_tree() { 57 | root = newnode(); 58 | for(;;) { 59 | char ch; 60 | while(ch = getchar(), isspace(ch)); 61 | if(ch == EOF) return false; 62 | ch = getchar(); 63 | if(ch == ')') break; 64 | int val = ch - '0'; 65 | while(ch = getchar(), ch != ',') 66 | val = val * 10 + (ch - '0'); 67 | string path; 68 | while(ch = getchar(), ch != ')') 69 | path += ch; 70 | if(!add_node(path, val)) failed = true; 71 | } 72 | return true; 73 | } 74 | 75 | bool bfs(Node* root) { 76 | if(failed) return false; 77 | queue q; 78 | q.push(root); 79 | vector ans; 80 | while(q.size()) { 81 | int len = q.size(); 82 | for(int i = 0; i < len; i++) { 83 | auto u = q.front(); q.pop(); 84 | if(!u->has_val) return false; 85 | ans.push_back(u->val); 86 | if(u->left) q.push(u->left); 87 | if(u->right) q.push(u->right); 88 | } 89 | } 90 | for(int i = 0; i < ans.size(); i++) 91 | printf(i > 0 ? " %d" : "%d", ans[i]); 92 | puts(""); 93 | return true; 94 | } 95 | 96 | int main(void) { 97 | init(); 98 | while(read_tree()) { 99 | if(!bfs(root)) puts("not complete"); 100 | remove_tree(root); 101 | failed = false; 102 | } 103 | return 0; 104 | } -------------------------------------------------------------------------------- /ch7/uva10603.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | const int maxn = 205; 9 | int vis[maxn][maxn], ans[maxn], cap[3]; 10 | 11 | struct Node { 12 | int jug[3], dist; 13 | bool operator<(const Node& rhs) const { 14 | return this->dist > rhs.dist; 15 | } 16 | }; 17 | 18 | Node trans(Node& node, int from, int to) { 19 | if(!node.jug[from] || node.jug[to] == cap[to]) return node; 20 | int tmp = min(node.jug[from], cap[to] - node.jug[to]); 21 | Node ans = node; 22 | ans.jug[from] -= tmp, ans.jug[to] += tmp; 23 | ans.dist += tmp; 24 | return ans; 25 | } 26 | 27 | void solve(int a, int b, int c, int d) { 28 | memset(vis, 0, sizeof(vis)); 29 | memset(ans, -1, sizeof(ans)); 30 | cap[0] = a, cap[1] = b, cap[2] = c; 31 | priority_queue q; 32 | ans[c] = 0, ans[0] = 0; 33 | vis[0][0] = 1; 34 | q.push({0, 0, c, 0}); 35 | while(q.size()) { 36 | auto t = q.top(); q.pop(); 37 | for(int i = 0; i < 3; i++) { 38 | int td = t.jug[i]; 39 | if(ans[td] < 0 || t.dist < ans[td]) 40 | ans[td] = t.dist; 41 | } 42 | if(ans[d] >= 0) break; 43 | for(int i = 0; i < 3; i++) { 44 | for(int j = 0; j < 3; j++) { 45 | if(i == j) continue; 46 | Node next = trans(t, i, j); 47 | int na = next.jug[0], nb = next.jug[1]; 48 | if(vis[na][nb]) continue; 49 | vis[na][nb] = 1; 50 | // dont update answer here 51 | // cause it may cause an early termination of the loop 52 | // with incorrect answer 53 | // for example, d liter water appear with a dist bigger than the answer 54 | q.push(next); 55 | } 56 | } 57 | } 58 | while(d >= 0) { 59 | if(ans[d] >= 0) { 60 | printf("%d %d\n", ans[d], d); 61 | return; 62 | } 63 | d--; 64 | } 65 | } 66 | 67 | int main(void) { 68 | #ifdef LOCAL 69 | freopen("uva10603.in", "r", stdin); 70 | freopen("uva10603.out", "w", stdout); 71 | #endif 72 | int T, a, b, c, d; 73 | scanf("%d", &T); 74 | while(T--) { 75 | scanf("%d%d%d%d", &a, &b, &c, &d); 76 | solve(a, b, c, d); 77 | } 78 | return 0; 79 | } 80 | 81 | // 计算出倒出d liter water的最小转移量 82 | // 若无法导出d liter water,计算出最接近d liter水量时的最小倒水量 83 | // 3 jugs represent a state together. 84 | // 1 state -> many states, record the poured amount to each state 85 | // every time the state transists, check if the gereated liter is new or poured amount is less 86 | // 87 | // because the total amount is certain, so we can use 2 dimension to represent 3 jugs, that is the state 88 | // use array to record liter -> minimum poured water -------------------------------------------------------------------------------- /ch7/uva11212.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int count(string& s) { 8 | int ans = 0; 9 | for(int i = 0; i < s.size(); i++) { 10 | if(i + 1 < s.size() && s[i + 1] != s[i] + 1) 11 | ans++; 12 | } 13 | if(s.back() != ('0' + s.size())) ans++; 14 | return ans; 15 | } 16 | 17 | // int solve(string& s) { 18 | // unordered_map map; 19 | // queue q; 20 | // map[s] = 0; 21 | // q.push({count(s), s}); 22 | // while(q.size()) { 23 | // auto t = q.front(); q.pop(); 24 | // if(t.first == 0) return map[t.second]; 25 | // auto str = t.second; 26 | // for(int i = 0; i < str.size(); i++) { 27 | // for(int j = i + 1; j <= str.size(); j++) { 28 | // auto rest = str.substr(0, i) + str.substr(j); 29 | // for(int k = 1; k <= rest.size(); k++) { 30 | // auto nx = rest.substr(0, k) + str.substr(i, j - i) + rest.substr(k); 31 | // int d = map[str] + 1, h = count(nx); 32 | // if(!map.count(nx)) { 33 | // map[nx] = d; 34 | // q.push({h, nx}); 35 | // } 36 | // } 37 | // } 38 | // } 39 | // } 40 | // return -1; 41 | // } 42 | 43 | bool dfs(string& str, int maxd, int d) { 44 | int h = count(str); 45 | if(3 * maxd < h + 3 * d) return false; 46 | if(h == 0) return true; 47 | for(int i = 0; i < str.size(); i++) { 48 | for(int j = i + 1; j <= str.size(); j++) { 49 | auto rest = str.substr(0, i) + str.substr(j); 50 | for(int k = 1; k <= i; k++) { 51 | auto nx = rest.substr(0, k) + str.substr(i, j - i) + rest.substr(k); 52 | if(dfs(nx, maxd, d + 1)) return true; 53 | } 54 | } 55 | } 56 | return false; 57 | } 58 | 59 | int main(void) { 60 | #ifdef LOCAL 61 | freopen("uva11212.in", "r", stdin); 62 | freopen("uva11212.out", "w", stdout); 63 | #endif 64 | int n; 65 | int rnd = 0; 66 | while(scanf("%d", &n), n) { 67 | string s; 68 | int t; 69 | for(int i = 0; i < n; i++) 70 | scanf("%d", &t), s += to_string(t); 71 | int ans = 0; 72 | if(count(s) != 0) { 73 | for(int i = 1; i < n; i++) { 74 | if(dfs(s, i, 0)) { 75 | ans = i; break; 76 | } 77 | } 78 | } 79 | printf("Case %d: %d\n", ++rnd, ans); 80 | // printf("Case %d: %d\n", ++rnd, solve(s)); 81 | } 82 | return 0; 83 | } 84 | 85 | // 看了书本 86 | // 假设还有h个数字的后继数字无效,又每次最多3个数字恢复正常 87 | // 所以,后续至少h / 3步 88 | // 若h / 3 + d > maxd,则剪枝 89 | 90 | // 字符串是一个状态state 91 | // 对于每个state,找到连续的片段,然后找到正确的2个位置,生成2个新状态 92 | // 对于每个状态,记录有多少个后续数字有问题 -------------------------------------------------------------------------------- /ch7/uva1603-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const int maxn = 60, maxm = 61; 6 | int size[maxn], fullsize[maxn]; 7 | bool contains[maxn][maxm], exists[maxm]; 8 | int n, sqcnt; 9 | 10 | int rowstick(int i, int j) { 11 | return (2*n+1)*i+j+1; 12 | } 13 | 14 | int colstick(int i, int j) { 15 | return n+1+(2*n+1)*i+j; 16 | } 17 | 18 | int fullstickamount(int n) { 19 | return 2*n*(n+1); 20 | } 21 | 22 | void init() { 23 | int k; 24 | scanf("%d%d", &n, &k); 25 | for(int i = 1; i <= fullstickamount(n); i++) exists[i] = true; 26 | for(int i = 0; i < k; i++) { 27 | int t; scanf("%d", &t); 28 | exists[t] = false; 29 | } 30 | memset(contains, false, sizeof contains); 31 | sqcnt = 0; 32 | // 枚举大小从小到大,很重要 33 | // 如果先按左上坐标,再按长度需要300ms+- 34 | // 先按长度,再按左上坐标,只需要20ms+- 35 | for(int len = 1; len <= n; len++) { 36 | for(int i = 0; i <= n - len ; i++) { 37 | for(int j = 0; j <= n - len; j++) { 38 | size[sqcnt] = 0; 39 | fullsize[sqcnt] = 4 * len; 40 | for(int k = 0; k < len; k++) { 41 | int arr[] = {rowstick(i, j+k), rowstick(i+len, j+k), colstick(i+k, j), colstick(i+k, j+len)}; 42 | for(int t = 0; t < 4; t++) { 43 | if(exists[arr[t]]) size[sqcnt]++; 44 | contains[sqcnt][arr[t]] = true; 45 | } 46 | } 47 | sqcnt++; 48 | } 49 | } 50 | } 51 | } 52 | 53 | int find_square() { 54 | for(int i = 0; i < sqcnt; i++) 55 | if(size[i] == fullsize[i]) return i; 56 | return -1; 57 | } 58 | 59 | int ans; 60 | 61 | void dfs(int d) { 62 | if(d >= ans) return; 63 | int k = find_square(); 64 | if(k == -1) { 65 | ans = d; 66 | return; 67 | } 68 | // 遍历每条边 69 | for(int i = 1; i <= fullstickamount(n); i++) { 70 | if(contains[k][i]) { 71 | for(int j = 0; j < sqcnt; j++) 72 | if(contains[j][i]) size[j]--; 73 | dfs(d+1); 74 | for(int j = 0; j < sqcnt; j++) 75 | if(contains[j][i]) size[j]++; 76 | } 77 | } 78 | } 79 | 80 | int main(void) { 81 | int T; scanf("%d", &T); 82 | while(T--) { 83 | init(); 84 | ans = 10000; 85 | dfs(0); 86 | printf("%d\n", ans); 87 | } 88 | return 0; 89 | } 90 | 91 | // 看了Rujia Liu的题解,这建模有点复杂,但是解是真的简洁优雅。。。 92 | // 每一步首先找到最小的完整正方形,因为小的必然破坏大的,但是大的不一定破坏小的 93 | // 枚举所有边,每次只拆掉一条,并且递归,递归结束后恢复现场 94 | // 最多有2*5*6 = 60个正方形,编号 95 | // 1. 为了快速知道正方形是否完整,可以维护正方形的当前存在边的总数,以及完整时边的总数 96 | // 2. 遍历每条边的时候,需要修改包含这条边的正方形的存在边的总数, 97 | // 需要通过正方形编号,查询正方形是否包含某条边 98 | 99 | // 1. size[n], fullsize[n] 100 | // 2. contains[n][2*n(n+1)] 101 | 102 | // 最大的收获可能是建模吧。。。 -------------------------------------------------------------------------------- /ch7/uva211.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int m = 7, n = 8; 7 | // used for bone, vis for grid 8 | bool used[m][n], vis[m][n]; 9 | // g for input grid, ex for existence of bone 10 | int g[m][n], ex[m][n], ans[m][n]; 11 | int anscnt, rest = 28; 12 | // 只往右或往下搜索,减少重复 13 | int dx[] = {1,0}, dy[] = {0,1}; 14 | 15 | bool read_input() { 16 | for(int i = 0; i < m; i++) { 17 | for(int j = 0; j < n; j++) { 18 | int t; 19 | if(scanf("%d", &t) == EOF) return false; 20 | g[i][j] = t; 21 | } 22 | } 23 | return true; 24 | } 25 | 26 | // 因为只往上或往下搜索,所以已处理部分位于左上角 27 | // 因此,查找右边界或下边界未访问的部分 28 | pair next() { 29 | for(int i = 0; i < m; i++) { 30 | for(int j = 0; j < n; j++) { 31 | if(!vis[i][j]) return {i, j}; 32 | } 33 | } 34 | return {-1, -1}; 35 | } 36 | 37 | bool invalid(int a, int b) { 38 | return a < 0 || a >= m || b < 0 || b >= n || vis[a][b]; 39 | } 40 | 41 | void bfs(int sx, int sy) { 42 | if(rest == 0) { 43 | anscnt++; 44 | puts("\n"); 45 | for(int i = 0; i < m; i++) { 46 | for(int j = 0; j < n; j++) { 47 | printf("%4d", ans[i][j]); 48 | } 49 | printf("\n"); 50 | } 51 | return; 52 | } 53 | if(invalid(sx, sy)) return; 54 | vis[sx][sy] = true; 55 | for(int i = 0; i < 2; i++) { 56 | int a = sx + dx[i], b = sy + dy[i]; 57 | if(invalid(a,b)) continue; 58 | int j = g[sx][sy], k = g[a][b]; 59 | if(!ex[j][k] || used[j][k]) continue; 60 | used[j][k] = used[k][j] = vis[a][b] = true; 61 | ans[sx][sy] = ans[a][b] = ex[j][k]; 62 | rest--; 63 | auto p = next(); 64 | bfs(p.first, p.second); 65 | rest++; 66 | used[j][k] = used[k][j] = vis[a][b] = false; 67 | } 68 | vis[sx][sy] = false; 69 | } 70 | 71 | int main(void) { 72 | #ifdef LOCAL 73 | freopen("uva211.in", "r", stdin); 74 | freopen("uva211.out", "w", stdout); 75 | #endif 76 | int tcnt = 0; 77 | for(int i = 0; i <= 6; i++) 78 | for(int j = i; j <= 6; j++) ex[i][j] = ex[j][i] = ++tcnt; 79 | int cnt = 0; 80 | while(read_input()) { 81 | if(cnt++ > 0) puts("\n\n\n\n"); 82 | printf("Layout #%d:\n\n\n", cnt); 83 | for(int i = 0; i < m; i++) { 84 | for(int j = 0; j < n; j++) { 85 | printf("%4d", g[i][j]); 86 | } 87 | printf("\n"); 88 | } 89 | printf("\nMaps resulting from layout #%d are:\n", cnt); 90 | anscnt = 0; 91 | bfs(0, 0); 92 | printf("\n\nThere are %d solution(s) for layout #%d.\n", anscnt, cnt); 93 | } 94 | return 0; 95 | } 96 | 97 | // 暴力搜索 98 | // 每一步搜索2个位置,然后选择下一个位置 99 | // 当所有格子都被搜索完成,那么生成了一个编号 100 | 101 | // 如何判断2个位置有效呢? 102 | // 1. 不越界 103 | // 2. 存在符合条件的未被使用的骨牌 104 | 105 | // 1. bool数组标记位置使用状态 106 | // 2. 表示骨牌的使用状态, 二维数组 107 | // 判断骨牌是否存在,二维数组。。。 -------------------------------------------------------------------------------- /ch6/uva1599.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int N = 1e5 + 10, M = 4e5 + 10; 8 | 9 | int h[N], e[M], ne[M], color[M], idx; 10 | int n, m; 11 | int dist[N]; 12 | bool used[N]; 13 | 14 | void init() { 15 | memset(h, -1, sizeof(h)); 16 | idx = 0; 17 | memset(dist, -1, sizeof(dist)); 18 | } 19 | 20 | void insert(int a, int b, int c) { 21 | e[idx] = b, color[idx] = c, ne[idx] = h[a], h[a] = idx++; 22 | } 23 | 24 | void rev_bfs() { 25 | memset(used, 0, sizeof(used)); 26 | dist[n] = 0; 27 | used[n] = true; 28 | queue q; 29 | q.push(n); 30 | while(q.size()) { 31 | auto t = q.front(); q.pop(); 32 | for(int i = h[t]; i != -1; i = ne[i]) { 33 | int j = e[i]; 34 | if(!used[j]) { 35 | dist[j] = dist[t] + 1; 36 | used[j] = true; 37 | q.push(j); 38 | } 39 | } 40 | } 41 | } 42 | 43 | void bfs() { 44 | vector ans; 45 | vector v; 46 | v.push_back(1); 47 | memset(used, 0, sizeof(used)); 48 | used[1] = true; 49 | for(int i = 0; i < dist[1]; i++) { 50 | // 因为我们需要的是color而已,所以即使在某一层有多条边的color相同 51 | // 也不影响当前层结果 52 | // 只需要将所有边color相同的终点保存起来,以便寻找下一层的最小color 53 | int minc = 1e9 + 1; 54 | for(int k = 0; k < v.size(); k++) { 55 | int t = v[k]; 56 | for(int i = h[t]; i != -1; i = ne[i]) { 57 | int j = e[i]; 58 | if(dist[j] == dist[t] - 1 && color[i] < minc) { 59 | minc = color[i]; 60 | } 61 | } 62 | } 63 | ans.push_back(minc); 64 | vector v2; 65 | int tsize = v.size(); 66 | for(int k = 0; k < v.size(); k++) { 67 | int t = v[k]; 68 | for(int i = h[t]; i != -1; i = ne[i]) { 69 | int j = e[i]; 70 | if(dist[j] == dist[t] - 1 && !used[j] && color[i] == minc) 71 | used[j] = true, v2.push_back(j); 72 | } 73 | } 74 | v = v2; 75 | } 76 | printf("%d\n", ans.size()); 77 | for(int i = 0; i < ans.size(); i++) 78 | printf(i > 0 ? " %d" : "%d", ans[i]); 79 | puts(""); 80 | } 81 | 82 | int main(void) { 83 | while(scanf("%d%d", &n, &m) == 2) { 84 | init(); 85 | for(int i = 0; i < m; i++) { 86 | int a, b, c; scanf("%d%d%d", &a, &b, &c); 87 | insert(a, b, c), insert(b, a, c); 88 | } 89 | rev_bfs(); 90 | bfs(); 91 | } 92 | return 0; 93 | } 94 | 95 | // 无权最短路,第一反应是BFS 96 | // 按照题目要求,要找出所有的最短路 97 | // BFS的停止条件是,全部点都已经遍历过了 98 | // BFS进入队列的条件是,点到起点的距离未被更新 99 | 100 | // 下一个问题是:如何找到字典序最小的路径呢? 101 | // 第一反应:按照层次遍历,每次只选择dist + 1的点中字典序最小的一个 102 | // 问题是:很可能存在一条到达其他点的路径,比到达终点的路径字典序更小 103 | // 因此,寻找路径的时候,应该从终点开始,每次只选择dist - 1的点中,字典序更大还是更小的一个呢? 104 | // 没有意义,因为我们需要比较的是从起点开始的字典序,而不是终点开始的 105 | 106 | // 反过来想一想,BFS从1到N和从N到1,1和N之间的最短路是不变的 107 | // 如果从N到1做BFS,然后从1开始层次遍历,每次只选择dist + 1的点中,字典序更小的一个,就看可以找到答案了 108 | 109 | // 自作聪明地想了很久,如何只需要一次BFS?浪费了很多时间都没想出来,还是功力不够。。。 110 | // 还是要注意控制时间,不然就失去了做题的意义 -------------------------------------------------------------------------------- /ch7/uva1602.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | typedef pair pii; 9 | 10 | #define FOR_CELL(c, p) for(auto c = (p).begin(); c != (p).end(); ++c) 11 | #define x first 12 | #define y second 13 | 14 | const int maxn = 11; 15 | int ans[maxn][maxn][maxn]; 16 | int dx[] = {0,0,-1,1}, dy[] = {-1,1,0,0}; 17 | int n, w, h; 18 | set> poly[maxn]; 19 | 20 | set normalize(const set& p) { 21 | int minX = 11, minY = 11; 22 | FOR_CELL(c, p) minX = min(minX, c->x), minY = min(minY, c->y); 23 | set ans; 24 | FOR_CELL(c, p) ans.insert({c->x - minX, c->y - minY}); 25 | return ans; 26 | } 27 | 28 | set rotate(const set& p) { 29 | set ans; 30 | // inspired by from Rujia Liu 31 | // 经过笔算,确实有旋转效果。。。 32 | // 每次只需要交换横纵坐标位置,并且将纵坐标取相反数,就有逆时针旋转的后果 33 | // 而经我试验,每次交换横纵坐标位置,并且将横坐标取相反数,就有逆时针旋转的效果 34 | FOR_CELL(c, p) ans.insert({-c->y, c->x}); 35 | return normalize(ans); 36 | } 37 | 38 | set flip(const set& p) { 39 | set ans; 40 | FOR_CELL(c, p) ans.insert({c->x, -c->y}); 41 | return normalize(ans); 42 | } 43 | 44 | void check_unique(const set& p0, const pii cell) { 45 | auto p = p0; 46 | p.insert(cell); 47 | int n = p.size(); 48 | p = normalize(p); 49 | for(int i = 0; i < 4; i++) { 50 | if(poly[n].count(p)) return; 51 | p = rotate(p); 52 | } 53 | p = flip(p); 54 | for(int i = 0; i < 4; i++) { 55 | if(poly[n].count(p)) return; 56 | p = rotate(p); 57 | } 58 | poly[n].insert(p); 59 | } 60 | 61 | void generate() { 62 | set s = {{0,0}}; 63 | poly[1].insert(s); 64 | for(int i = 2; i <= 10; i++) { 65 | for(auto p = poly[i-1].begin(); p != poly[i-1].end(); p++) { 66 | FOR_CELL(c, *p) { 67 | for(int i = 0; i < 4; i++) { 68 | pii cell = {c->x + dx[i], c->y + dy[i]}; 69 | if(!p->count(cell)) check_unique(*p, cell); 70 | } 71 | } 72 | } 73 | } 74 | for(int n = 1; n <= 10; n++) { 75 | for(int w = 1; w <= 10; w++) { 76 | for(int h = 1; h <= 10; h++) { 77 | int cnt = 0; 78 | for(auto p = poly[n].begin(); n <= w*h && p != poly[n].end(); p++) { 79 | int maxX = 0, maxY = 0; 80 | FOR_CELL(c, *p) maxX = max(maxX, c->x), maxY = max(maxY, c->y); 81 | if(min(maxX, maxY) < min(h, w) && max(maxX, maxY) < max(h, w)) cnt++; 82 | } 83 | ans[n][w][h] = cnt; 84 | } 85 | } 86 | } 87 | } 88 | 89 | int main(void) { 90 | #ifdef LOCAL 91 | freopen("uva1602.in", "r", stdin); 92 | freopen("uva1602.out", "w", stdout); 93 | #endif 94 | generate(); 95 | while(scanf("%d%d%d",&n,&w,&h) == 3) 96 | printf("%d\n", ans[n][w][h]); 97 | return 0; 98 | } 99 | 100 | // 又是学习如何建模的一天。。。这次的内容是俄罗斯方块 101 | // 用{x,y}表示一个方块,用方块的set代表一个状态 102 | // 枚举的时候,从n-1个方块组成的状态中,增加一个方块 103 | // 去重的时候 104 | // 1. 首先要规范化,将一个状态中的所有方块移动到第一象限; 查看已有的同数量方块中,有没有一样的 105 | // 2. 4个方向旋转,并规范化,查看有没有一样的 106 | // 3. 翻转,并4个方向旋转,查看有没有一样的 107 | // 4. 如果都没有,那么把他添加到n个方块组成的状态的集合中 108 | 109 | // 枚举n,w,h, 查看符合要求的状态数量, 提前存起来 110 | 111 | -------------------------------------------------------------------------------- /ch6/uva1103-c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | // idea from Rujia Liu: 11 | // 給每个连通块唯一编号,那么背景白色的编号必为1 12 | // 对所有黑色连通分量的4连通邻居做检查,用集合记录内部白色连通分量的编号 13 | // 白色连通分量的个数就是集合大小 14 | // 思路分析: 15 | // 核心思路都是一样的:区分背景白色和文字内部白色 16 | // 1. 将每个文字单独复制到空白的背景上,再单独进行白色连通分量的统计 17 | // 这种思路,为了避免和其他文字的内部白色分量混淆,将文字单独复制到空白图, 18 | // 然后,空洞数量 = 白色分量数量 - 1,是为了和背景白色做区分 19 | // 2. Rujia Liu的思路,是通过编号来直接区分的 20 | // 编号为1的永远是白色背景,最后再统计每个黑色分量的编号非1的白色分量邻居 21 | // 因为不同的文字不会直接连接,所以这样内部空洞就可以和背景白色、其他文字内部的白色区分开 22 | // 总结:如果需要独立唯一区分,那么可以尝试编号!!!(和书里前面提到的:给字符串唯一ID是一个原理) 23 | 24 | const int M = 210, N = 210; 25 | int m, w, n, grid[M][N], tmp[M][N]; 26 | int dx[] = {0, 0, -1, 1}, dy[] = {1, -1, 0, 0}; 27 | char word[6] = {'W', 'A', 'K', 'J', 'S', 'D'}; 28 | char line[60]; 29 | 30 | bool is_invalid(int sx, int sy) { 31 | return sx < 0 || sx >= m || sy < 0 || sy >= n; 32 | } 33 | 34 | void mark(int sx, int sy, int id) { 35 | if(is_invalid(sx, sy)) return; 36 | if(tmp[sx][sy]) return; 37 | tmp[sx][sy] = id; 38 | for(int i = 0; i < 4; i++) { 39 | int a = sx + dx[i], b = sy + dy[i]; 40 | if(grid[a][b] == grid[sx][sy]) mark(a, b, id); 41 | } 42 | } 43 | 44 | void read_pic() { 45 | memset(grid, 0, sizeof(grid)); 46 | memset(tmp, 0, sizeof tmp); 47 | for(int i = 1; i <= m; i++) { 48 | scanf("%s", line); 49 | for(int j = 0; j < w; j++) { 50 | char ch = line[j]; 51 | int num; 52 | if(isdigit(ch)) num = ch - '0'; 53 | else num = 10 + (ch - 'a'); 54 | for(int k = 3; k >= 0; k--) { 55 | grid[i][1 + 4 * j + k] = num & 1; 56 | num >>= 1; 57 | } 58 | } 59 | } 60 | n = 4 * w; 61 | m += 2, n += 2; 62 | } 63 | 64 | unordered_map> map; 65 | 66 | void check_nbrs(int sx, int sy) { 67 | for(int k = 0; k < 4; k++) { 68 | int a = sx + dx[k], b = sy + dy[k]; 69 | if(!is_invalid(a, b) && grid[a][b] != 1 && tmp[a][b] != 1) 70 | map[tmp[sx][sy]].insert(tmp[a][b]); 71 | } 72 | } 73 | 74 | int main(void) { 75 | int cnt = 0; 76 | while(scanf("%d%d\n", &m, &w) != EOF, m) { 77 | read_pic(); 78 | int num = 0; 79 | set idset; 80 | for(int i = 0; i < m; i++) 81 | for(int j = 0; j < n; j++) 82 | if(!tmp[i][j]) { 83 | // mark the component with uni-id 84 | mark(i, j, ++num); 85 | // record the black component id for subsequent neighbour checking 86 | if(grid[i][j]) idset.insert(num); 87 | } 88 | 89 | // count neighbours expect the background white component 90 | // always has id of 1 91 | map.clear(); 92 | for(auto id : idset) map[id] = set(); 93 | for(int i = 0; i < m; i++) 94 | for(int j = 0; j < n; j++) 95 | if(grid[i][j]) check_nbrs(i, j); 96 | 97 | vector v; 98 | for(auto& t: map) v.push_back(word[t.second.size()]); 99 | sort(v.begin(), v.end()); 100 | printf("Case %d: ", ++cnt); 101 | for(auto& ch : v) putchar(ch); 102 | puts(""); 103 | } 104 | return 0; 105 | } -------------------------------------------------------------------------------- /ch7/uva1354.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | typedef struct Tree { 11 | double L, R; 12 | Tree() : L(0), R(0) {} 13 | } Tree; 14 | 15 | const int maxn = 6; 16 | double r; 17 | int s, sto[maxn], sum[1 << maxn]; 18 | vector trees[1 << maxn]; 19 | bool vis[1 << maxn]; 20 | 21 | void dfs(int subset) { 22 | if(vis[subset]) return; 23 | vis[subset] = true; 24 | if(!(subset&(subset - 1))) { 25 | trees[subset].push_back(Tree()); 26 | return; 27 | } 28 | // 讲解一下如何用位运算枚举子集: 29 | // 2个核心:1. 通过left - 1不断枚举小于subset的数 2. 通过&与运算,去除冗余的状态 30 | // 前者保证不漏,后者保证不重 31 | for(int left = subset&(subset - 1); left; left = (left-1) & subset) { 32 | int right = subset ^ left; 33 | dfs(left); dfs(right); 34 | double dl = (double)sum[right] / sum[subset]; 35 | double dr = (double)sum[left] / sum[subset]; 36 | for(auto& lt : trees[left]) { 37 | for(auto& rt : trees[right]) { 38 | Tree t; 39 | // 小细节。。。。。。 40 | t.L = max(lt.L + dl, rt.L - dr); 41 | t.R = max(rt.R + dr, lt.R - dl); 42 | if(t.L + t.R < r) trees[subset].push_back(t); 43 | } 44 | } 45 | } 46 | } 47 | 48 | int main(void) { 49 | #ifdef LOCAL 50 | freopen("uva1354.in", "r", stdin); 51 | freopen("uva1354.out", "w", stdout); 52 | #endif 53 | int T; 54 | auto startt = clock(); 55 | scanf("%d", &T); 56 | while(T--) { 57 | scanf("%lf%d", &r, &s); 58 | for(int i = 0; i < s; i++) scanf("%d", &sto[i]); 59 | // 提前计算好重量 60 | for(int i = 0; i < (1 << s); i++) { 61 | trees[i].clear(); 62 | sum[i] = 0; 63 | for(int j = 0; j < s; j++) 64 | if(i & (1 << j)) sum[i] += sto[j]; 65 | } 66 | memset(vis, 0, sizeof(vis)); 67 | int fullset = (1 << s) - 1; 68 | dfs(fullset); 69 | double ans = -1.0; 70 | for(auto& val : trees[fullset]) 71 | ans = max(ans, val.L + val.R); 72 | printf("%.15lf\n", ans); 73 | } 74 | auto endt = clock(); 75 | cout << "Totle Time : " <<(double)(endt - startt) / CLOCKS_PER_SEC << "s" << endl; 76 | return 0; 77 | } 78 | 79 | 80 | // 枚举所有可能的风铃 81 | // 一个节点,可能是石头或者风铃 82 | // 子节点,要么有2个,要么无 83 | // 84 | // 如果一个节点是石头,如何判断是否有效呢? 85 | // 是没办法的,因为无法知道sibling的重量 86 | // 如果一个节点是否风铃,如何判断是否有效呢? 87 | // 也是没办法的,不仅不知道sibling的重量,甚至都无法知道自己的重量 88 | // 89 | // 以上思路,听起来就很麻烦。。。 90 | // 91 | // 可不可以直接枚举各种可能的二叉树,然后验证二叉树的平衡性和宽度呢? 92 | // 通过后序遍历,能够获得左右子节点的重量,由此可以判断平衡性 93 | // 如果不平衡,则当前二叉树无效 94 | // 如果平衡,则告知上一级重量 95 | // 那么,宽度如何判断呢?返回左右宽度到上一级 96 | // 上一级可以由此计算出上一级的左右宽度 97 | // 98 | // 这个平衡性似乎没有意义,去掉。 99 | // 所以就是枚举二叉树并且回溯得到宽度 100 | // 要求是使用所有的石头,并且宽度要小于房间 101 | // 102 | // 那么,如何枚举二叉树呢? 103 | // 我确实不会做。。。确实菜。。。 104 | // 所以去看了rujia liu的题解,以及力扣上一道叫All Possible Full Binary Trees的题目 105 | // APFBT这道题目呢,只规定了枚举所有树的形态,但递归和子集的思想上和rujia liu的是一样的 106 | // 那除了思想上,解法上有什么不同呢? 107 | // 因为这道题规定的不只是树的形态,还规定了叶子节点的值必须是石头的值 108 | // 因此不能像枚举二叉树形态一样,只需要节点数量作为参数,而是还需要知道对应的具体节点子集 109 | // 110 | // 所以说,递归函数的入参,就是节点的子集 111 | // 然后,将这个子集分为2个非空子集(非空,因为题目要求风铃的两边必须不能为空) 112 | // 递归调用这两个非空子集,保留他们每个可能的最大左右距离(因为左右子集也是有多种形态的) 113 | // 由于子集是已知的,就能算出当前风铃两边的长度, 114 | // 再结合递归调用的结果,算出当前子集的所有可能性 -------------------------------------------------------------------------------- /ch6/uva506.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | // 输出: 13 | // 所有命令都需要echo 14 | // INSTALL命令:1. 按照依赖逆序installing; 2. alredy installed 15 | // REMOVE命令:1. 按照依赖顺序Removing; 3. still needed 16 | // 被implictly installed的软件,不能使用REMOVE命令显示删除 17 | 18 | // 为每个软件分配一个ID 19 | // status表示软件的安装状态 20 | // 保存 被依赖软件 -> 依赖软件 的图,INSTALL的时候可以用来按顺序检查和安装所需的软件 21 | // REMOVE需要逆序删除,因此需要保存 依赖软件 -> 被依赖软件的图 22 | 23 | const int N = 10010; 24 | 25 | unordered_map itemidmap; 26 | vector vec; 27 | 28 | vector depend[N]; 29 | int depcnt[N], status[N]; 30 | vector installed; 31 | 32 | int ID(string s) { 33 | if(!itemidmap.count(s)) vec.push_back(s), itemidmap[s] = vec.size() - 1; 34 | return itemidmap[s]; 35 | } 36 | 37 | void add_dep(int a, int b) { 38 | depend[a].push_back(b); 39 | } 40 | 41 | // 42 | void install(int id, int st) { 43 | if(status[id]) return; 44 | for(int i = 0; i < depend[id].size(); i++) { 45 | int tid = depend[id][i]; 46 | if(!status[tid]) install(tid, 2); 47 | depcnt[tid]++; 48 | } 49 | status[id] = st; 50 | printf(" Installing %s\n", vec[id].c_str()); 51 | installed.push_back(id); 52 | } 53 | 54 | // 未安装的软件被显式删除,提示未安装 55 | // 安装的软件被显式删除,如果depcnt > 0,删除失败 56 | // 安装的软件被隐式删除,如果depcnt == 0,status == 2 57 | void remove(int id, int st) { 58 | // 显式删除,需要检查depcnt,如果 > 0,删除失败 59 | // 否则,删除,并且更新那些被当前软件依赖的软件 60 | // 若某个被依赖软件 --depcnt == 0 && status == 2,那么递归的删除这个软件 61 | if(depcnt[id] > 0 || !status[id]) return; 62 | status[id] = 0; 63 | installed.erase(remove(installed.begin(), installed.end(), id), installed.end()); 64 | printf(" Removing %s\n", vec[id].c_str()); 65 | for(int i = 0; i < depend[id].size(); i++) { 66 | int tid = depend[id][i]; 67 | if(--depcnt[tid] == 0 && status[tid] == 2) remove(tid, 2); 68 | } 69 | } 70 | 71 | void list_items() { 72 | for(auto& t : installed) 73 | printf(" %s\n", vec[t].c_str()); 74 | } 75 | 76 | int main(void) { 77 | #ifdef LOCAL 78 | freopen("uva506.in", "r", stdin); 79 | freopen("uva506.out", "w", stdout); 80 | #endif 81 | string cmd; 82 | string iname; 83 | string line; 84 | while(getline(cin, line)) { 85 | cout << line << endl; 86 | stringstream ss(line); 87 | ss >> cmd; 88 | if(cmd[0] == 'E') break; 89 | if(cmd[0] == 'D') { 90 | ss >> iname; 91 | int aid = ID(iname); 92 | while(ss >> iname) { 93 | int bid = ID(iname); 94 | add_dep(aid, bid); 95 | } 96 | } else if(cmd[0] == 'I') { 97 | ss >> iname; 98 | int id = ID(iname); 99 | if(status[id]) printf(" %s is already installed.\n", vec[id].c_str()); 100 | else install(id, 1); 101 | } else if(cmd[0] == 'R') { 102 | ss >> iname; 103 | int id = ID(iname); 104 | if(!status[id]) printf(" %s is not installed.\n", vec[id].c_str()); 105 | else if(depcnt[id] > 0) printf(" %s is still needed.\n", vec[id].c_str()); 106 | else remove(id, 1); 107 | } else if(cmd[0] == 'L') { 108 | list_items(); 109 | } 110 | } 111 | return 0; 112 | } -------------------------------------------------------------------------------- /ch6/uva816-b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | struct State { 9 | int x; 10 | int y; 11 | int dir; 12 | }; 13 | 14 | const int N = 10; 15 | bool st[N][N][4][3]; 16 | bool visited[N][N][4]; 17 | State pre[N][N][4]; 18 | queue q; 19 | State entra, dest; 20 | char maze_name[24]; 21 | 22 | const string dirs = "NESW"; 23 | const string turns = "FLR"; 24 | 25 | int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 26 | 27 | int dir_id(char ch) { 28 | for(int i = 0; i < 4; i++) 29 | if(dirs[i] == ch) return i; 30 | return -1; 31 | } 32 | 33 | int turn_id(char ch) { 34 | for(int i = 0; i < 3; i++) 35 | if(turns[i] == ch) return i; 36 | return -1; 37 | } 38 | 39 | State trans(const State& u, int turn) { 40 | int dir = u.dir; 41 | if(turn == 1) dir = (dir - 1 + 4) % 4; 42 | if(turn == 2) dir = (dir + 1) % 4; 43 | return State {u.x + dx[dir], u.y + dy[dir], dir}; 44 | } 45 | 46 | bool inside(int r, int c) { 47 | return r >= 1 && r <= 9 && c >= 1 && c <= 9; 48 | } 49 | 50 | void print_ans() { 51 | vector> v; 52 | int x = dest.x, y = dest.y, dir = dest.dir; 53 | v.push_back({x, y}); 54 | do { 55 | auto& state = pre[x][y][dir]; 56 | v.push_back({state.x, state.y}); 57 | x = state.x, y = state.y, dir = state.dir; 58 | } while(x != entra.x || y != entra.y); 59 | for(int j = v.size() - 1; j >= 0;) { 60 | printf(" "); 61 | for(int i = 0; i < 10 && j >= 0; i++, j--) { 62 | auto t = v[j]; 63 | printf(" (%d,%d)", t.first, t.second); 64 | } 65 | puts(""); 66 | } 67 | } 68 | 69 | bool solve() { 70 | memset(visited, 0, sizeof visited); 71 | auto t = trans(entra, turn_id('F')); 72 | pre[t.x][t.y][t.dir] = entra; 73 | visited[t.x][t.y][t.dir] = true; 74 | queue q; 75 | q.push(t); 76 | while(q.size()) { 77 | auto u = q.front(); q.pop(); 78 | if(u.x == dest.x && u.y == dest.y) { 79 | dest.dir = u.dir; 80 | return true; 81 | } 82 | for(int i = 0; i < 3; i++) { 83 | if(!st[u.x][u.y][u.dir][i]) continue; 84 | auto v = trans(u, i); 85 | if(!visited[v.x][v.y][v.dir] && inside(v.x, v.y)) { 86 | visited[v.x][v.y][v.dir] = true; 87 | pre[v.x][v.y][v.dir] = u; 88 | q.push(v); 89 | } 90 | } 91 | } 92 | return false; 93 | } 94 | 95 | 96 | int main(void) { 97 | while(scanf("%s", maze_name), strcmp(maze_name, "END") != 0) { 98 | int x, y; char str[10]; 99 | memset(st, 0, sizeof(st)); 100 | scanf("%d%d%s", &x, &y, str); 101 | entra = State{x, y, dir_id(str[0])}; 102 | scanf("%d%d", &x, &y); 103 | dest = {x, y, 0}; 104 | while(scanf("%d", &x), x) { 105 | scanf("%d", &y); 106 | while(scanf("%s", str), strcmp(str, "*") != 0) { 107 | int dir = dir_id(str[0]); 108 | for(int i = 1; i < strlen(str); i++) { 109 | st[x][y][dir][turn_id(str[i])] = true; 110 | } 111 | } 112 | } 113 | printf("%s\n", maze_name); 114 | if(solve()) print_ans(); 115 | else puts(" No Solution Possible"); 116 | } 117 | return 0; 118 | } -------------------------------------------------------------------------------- /ch7/uva225-c.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int dx[] = {0,1,0,-1}, dy[] = {1,0,-1,0}; 9 | int sum[25], g[220][220]; 10 | char dirs[] = {'n','e','s','w'}; 11 | char path[20]; 12 | // 根据问题规模,走20次,其实最多也只是21 * 20 / 2 = 210 13 | // 而要出发后往回走,意味着超过210 / 2 = 105就没有无法返回了 14 | // 又因为可以往四个方向走,所以数组的大小是210,由于210是个边界值,为了保险起见,直接用220会更保险 15 | // 所以完全可以用一个二维数组来保存点的状态,但要注意因为坐标可能是负数,所以还需要加一个偏移量 16 | // 改造之后,只需要450ms,比我在洛谷看到的两个解答都更快 17 | // 但是,直接用g来判断障碍点,会遍历很多没必要的点,又会比方式b慢100+ms 18 | int n, k; 19 | int tot; 20 | 21 | bool invalid(int a, int b) { 22 | return abs(a) > 110 || abs(b) > 110; 23 | } 24 | 25 | void dfs(int sx, int sy, int dir, int step) { 26 | if(step == n + 1) { 27 | if(sx == 0 && sy == 0) { 28 | tot++; 29 | for(int i = 1; i <= n; i++) 30 | printf(i < n ? "%c" : "%c\n", path[i]); 31 | } 32 | return; 33 | } 34 | for(int i = 0; i < 4; i++) { 35 | // 奇偶性 36 | if(((dir ^ i) & 1) == 0) continue; 37 | int a = sx + step * dx[i]; 38 | int b = sy + step * dy[i]; 39 | if(invalid(a, b)) continue; 40 | if(g[a+110][b+110]) continue; 41 | // 哈密顿距离,剪枝 42 | if (abs(a) + abs(b) > sum[20] - sum[step]) continue; 43 | bool flag = true; 44 | int fx = min(a, sx), tx = max(a, sx); 45 | int fy = min(b, sy), ty = max(b, sy); 46 | // 这种方式会更慢,因为会遍历很多没必要的点 47 | // 而方式b,直接判断障碍点是否在线段上,由于障碍点数量最多只有50个,比较少 48 | // 所以,这种方式会更慢 49 | for(int i = fx; i <= tx; i++) 50 | for(int j = fy; j <= ty; j++) 51 | if(g[i+110][j+110] == -1) { 52 | flag = false; break; 53 | } 54 | 55 | if(flag) { 56 | // printf("%d,%d to %d,%d\n", sx, sy, a, b); 57 | path[step] = dirs[i]; 58 | g[a+110][b+110] = 1; 59 | dfs(a, b, i, step + 1); 60 | g[a+110][b+110] = 0; 61 | } 62 | } 63 | } 64 | 65 | int main(void) { 66 | #ifdef LOCAL 67 | freopen("uva225.in", "r", stdin); 68 | freopen("uva225.out", "w", stdout); 69 | #endif 70 | for(int i=1;i<=20;i++) sum[i]=sum[i-1]+i; 71 | int T; scanf("%d", &T); 72 | while(T--) { 73 | scanf("%d%d", &n, &k); 74 | memset(g, 0, sizeof(g)); 75 | for(int i = 0; i < k; i++) { 76 | int a, b; 77 | scanf("%d%d", &a, &b); 78 | if(invalid(a, b)) continue; 79 | g[a+110][b+110] = -1; 80 | } 81 | 82 | tot = 0; 83 | // ensw 84 | int ta[] = {1, 0, 2, 3}; 85 | for(auto i : ta) { 86 | path[1] = dirs[i]; 87 | int a = dx[i], b = dy[i]; 88 | if(g[a+110][b+110] == -1) continue; 89 | g[a+110][b+110] = 1; 90 | dfs(dx[i], dy[i], i, 2); 91 | g[a+110][b+110] = 0; 92 | } 93 | printf("Found %d golygon(s).\n\n", tot); 94 | } 95 | return 0; 96 | } 97 | 98 | 99 | // give n, k 100 | // find a path from (0,0) to (0,0) 101 | // 4 directions at 1st move, turn left or right at subsequent moves... 102 | // blocked intersections cannot go across 103 | // 104 | // time complexity: 4 * 2 ** (n-1) = 2 ** (n+1) = 2 ** (21) = 2e6 105 | // 106 | // enum left or right: 107 | // turn left or right: even <-> odd 108 | // 0,1,2,3 -> n,e,s,w 109 | // // 同一条路线,可以重复经过不能重复访问同一个路口又不说,醉了,uva的题目真的不止一次了。。。 -------------------------------------------------------------------------------- /ch6/uva806.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | const int N = 70; 10 | int n, num; 11 | char g[N][N]; 12 | vector treenums; 13 | 14 | bool is_2color(int r, int c, int len) { 15 | char color = g[r][c]; 16 | for(int i = r; i < r + len; i++) 17 | for(int j = c; j < c + len; j++) 18 | if(g[i][j] != color) return true; 19 | return false; 20 | } 21 | 22 | void img2tree(int r, int c, int len, vector& path) { 23 | if(!is_2color(r, c, len)) { 24 | if(g[r][c] == '0') return; 25 | int base = 1; 26 | int ans = 0; 27 | for(int i = 0; i < path.size(); i++) { 28 | ans += path[i] * base; 29 | base *= 5; 30 | } 31 | treenums.push_back(ans); 32 | return; 33 | } 34 | len >>= 1; 35 | path.push_back(1); 36 | img2tree(r, c, len, path); 37 | path.back() = 2; 38 | img2tree(r, c + len, len, path); 39 | path.back() = 3; 40 | img2tree(r + len, c, len, path); 41 | path.back() = 4; 42 | img2tree(r + len, c + len, len, path); 43 | path.pop_back(); 44 | } 45 | 46 | void tree2img(int r, int c, int len, vector& path, int depth) { 47 | if(depth == path.size()) { 48 | for(int i = r; i < r + len; i++) 49 | for(int j = c; j < c + len; j++) g[i][j] = '*'; 50 | return; 51 | } 52 | len >>= 1; 53 | int t = path[depth++]; 54 | if(t == 1) tree2img(r, c, len, path, depth); 55 | else if(t == 2) tree2img(r, c + len, len, path, depth); 56 | else if(t == 3) tree2img(r + len, c, len, path, depth); 57 | else if(t == 4) tree2img(r + len, c + len, len, path, depth); 58 | } 59 | 60 | void init_img(char ch) { 61 | for(int i = 0; i < n; i++) 62 | for(int j = 0; j < n; j++) g[i][j] = ch; 63 | } 64 | 65 | int main(void) { 66 | #ifdef LOCAL 67 | freopen("uva806.in", "r", stdin); 68 | freopen("uva806.out", "w", stdout); 69 | #endif 70 | int cnt = 0; 71 | while(scanf("%d", &n), n) { 72 | if(cnt > 0) printf("\n"); 73 | printf("Image %d\n", ++cnt); 74 | if(n > 0) { 75 | for(int i = 0; i < n; i++) 76 | scanf("%s", g[i]); 77 | 78 | vector path; 79 | treenums.clear(); 80 | img2tree(0, 0, n, path); 81 | sort(treenums.begin(), treenums.end()); 82 | for(int i = 0; i < treenums.size(); ) { 83 | for(int j = 0; j < 12 && i < treenums.size(); i++, j++) 84 | printf(j > 0 ? " %d" : "%d", treenums[i]); 85 | printf("\n"); 86 | } 87 | printf("Total number of black nodes = %d\n", treenums.size()); 88 | } else { 89 | n *= -1; 90 | int t; scanf("%d", &t); 91 | if(t == 0) init_img('*'), scanf("%d", &t); 92 | else if(t == -1) init_img('.'); 93 | else { 94 | init_img('.'); 95 | do { 96 | vector path; 97 | while(t) path.push_back(t % 5), t /= 5; 98 | tree2img(0, 0, n, path, 0); 99 | } while(scanf("%d", &t), t != -1); 100 | } 101 | for(int i = 0; i < n; i++) { 102 | for(int j = 0; j < n; j++) putchar(g[i][j]); 103 | printf("\n"); 104 | } 105 | } 106 | } 107 | return 0; 108 | } -------------------------------------------------------------------------------- /ch7/uva225.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | typedef pair pii; 11 | 12 | int dx[] = {0,1,0,-1}, dy[] = {1,0,-1,0}; 13 | int sum[25]; 14 | char dirs[] = {'n','e','s','w'}; 15 | char path[20]; 16 | unordered_map> xy; 17 | unordered_map> yx; 18 | auto phash = [](const pii& p){ return (size_t)(p.first * 31 + p.second); }; 19 | unordered_set set(10, phash); 20 | // 根据问题规模,走20次,其实最多也只是21 * 20 / 2 = 210 21 | // 而要出发后往回走,意味着超过210 / 2 = 105就没有无法返回了 22 | // 又因为可以往四个方向走,所以数组的大小是210,由于210是个边界值,为了保险起见,直接用220会更保险 23 | // 所以完全可以用一个二维数组来保存点的状态,但要注意因为坐标可能是负数,所以还需要加一个偏移量 24 | int n, k; 25 | int tot; 26 | 27 | void dfs(int sx, int sy, int dir, int step) { 28 | if(step == n + 1) { 29 | if(sx == 0 && sy == 0) { 30 | tot++; 31 | for(int i = 1; i <= n; i++) 32 | printf(i < n ? "%c" : "%c\n", path[i]); 33 | } 34 | return; 35 | } 36 | for(int i = 0; i < 4; i++) { 37 | // 奇偶性 38 | if(((dir ^ i) & 1) == 0) continue; 39 | int a = sx + step * dx[i]; 40 | int b = sy + step * dy[i]; 41 | if(set.count({a, b})) continue; 42 | // 哈密顿距离,剪枝 43 | if (abs(a) + abs(b) > sum[20] - sum[step]) continue; 44 | bool flag = true; 45 | if(i & 1) { 46 | int from = min(a, sx), to = max(a, sx); 47 | for(auto x : yx[sy]) { 48 | if(from <= x && x <= to) { 49 | flag = false; break; 50 | } 51 | } 52 | } else { 53 | int from = min(b, sy), to = max(b, sy); 54 | for(auto y : xy[sx]) { 55 | if(from <= y && y <= to) { 56 | flag = false; break; 57 | } 58 | } 59 | } 60 | if(flag) { 61 | // printf("%d,%d to %d,%d\n", sx, sy, a, b); 62 | path[step] = dirs[i]; 63 | set.insert({a, b}); 64 | dfs(a, b, i, step + 1); 65 | set.erase({a, b}); 66 | } 67 | } 68 | } 69 | 70 | int main(void) { 71 | #ifdef LOCAL 72 | freopen("uva225.in", "r", stdin); 73 | freopen("uva225.out", "w", stdout); 74 | #endif 75 | for(int i=1;i<=20;i++) sum[i]=sum[i-1]+i; 76 | int T; scanf("%d", &T); 77 | while(T--) { 78 | scanf("%d%d", &n, &k); 79 | xy.clear(), yx.clear(); 80 | for(int i = 0; i < k; i++) { 81 | int a, b; 82 | scanf("%d%d", &a, &b); 83 | xy[a].push_back(b), yx[b].push_back(a); 84 | } 85 | 86 | tot = 0; 87 | // ensw 88 | int ta[] = {1, 0, 2, 3}; 89 | for(auto i : ta) { 90 | path[1] = dirs[i]; 91 | set.insert({dx[i], dy[i]}); 92 | dfs(dx[i], dy[i], i, 2); 93 | set.erase({dx[i], dy[i]}); 94 | } 95 | printf("Found %d golygon(s).\n\n", tot); 96 | } 97 | return 0; 98 | } 99 | 100 | // give n, k 101 | // find a path from (0,0) to (0,0) 102 | // 4 directions at 1st move, turn left or right at subsequent moves... 103 | // blocked intersections cannot go across 104 | // 105 | // time complexity: 4 * 2 ** (n-1) = 2 ** (n+1) = 2 ** (21) = 2e6 106 | // 107 | // enum left or right: 108 | // turn left or right: even <-> odd 109 | // 0,1,2,3 -> n,e,s,w 110 | // 同一条路线,可以重复经过不能重复访问同一个路口又不说,醉了,uva的题目真的不止一次了。。。 -------------------------------------------------------------------------------- /ch7/uva225-b.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int dx[] = {0,1,0,-1}, dy[] = {1,0,-1,0}; 10 | int sum[25], g[220][220]; 11 | char dirs[] = {'n','e','s','w'}; 12 | char path[20]; 13 | unordered_map> xy; 14 | unordered_map> yx; 15 | // 根据问题规模,走20次,其实最多也只是21 * 20 / 2 = 210 16 | // 而要出发后往回走,意味着超过210 / 2 = 105就没有无法返回了 17 | // 又因为可以往四个方向走,所以数组的大小是210,由于210是个边界值,为了保险起见,直接用220会更保险 18 | // 所以完全可以用一个二维数组来保存点的状态,但要注意因为坐标可能是负数,所以还需要加一个偏移量 19 | // 改造之后,只需要450ms,比我在洛谷看到的两个解答都更快 20 | int n, k; 21 | int tot; 22 | 23 | bool invalid(int a, int b) { 24 | return abs(a) > 110 || abs(b) > 110; 25 | } 26 | 27 | void dfs(int sx, int sy, int dir, int step) { 28 | if(step == n + 1) { 29 | if(sx == 0 && sy == 0) { 30 | tot++; 31 | for(int i = 1; i <= n; i++) 32 | printf(i < n ? "%c" : "%c\n", path[i]); 33 | } 34 | return; 35 | } 36 | for(int i = 0; i < 4; i++) { 37 | // 奇偶性 38 | if(((dir ^ i) & 1) == 0) continue; 39 | int a = sx + step * dx[i]; 40 | int b = sy + step * dy[i]; 41 | if(invalid(a, b)) continue; 42 | if(g[a+110][b+110]) continue; 43 | // 哈密顿距离,剪枝 44 | if (abs(a) + abs(b) > sum[20] - sum[step]) continue; 45 | bool flag = true; 46 | if(i & 1) { 47 | int from = min(a, sx), to = max(a, sx); 48 | for(auto x : yx[sy]) { 49 | if(from <= x && x <= to) { 50 | flag = false; break; 51 | } 52 | } 53 | } else { 54 | int from = min(b, sy), to = max(b, sy); 55 | for(auto y : xy[sx]) { 56 | if(from <= y && y <= to) { 57 | flag = false; break; 58 | } 59 | } 60 | } 61 | if(flag) { 62 | // printf("%d,%d to %d,%d\n", sx, sy, a, b); 63 | path[step] = dirs[i]; 64 | g[a+110][b+110] = 1; 65 | dfs(a, b, i, step + 1); 66 | g[a+110][b+110] = 0; 67 | } 68 | } 69 | } 70 | 71 | int main(void) { 72 | #ifdef LOCAL 73 | freopen("uva225.in", "r", stdin); 74 | freopen("uva225.out", "w", stdout); 75 | #endif 76 | for(int i=1;i<=20;i++) sum[i]=sum[i-1]+i; 77 | int T; scanf("%d", &T); 78 | while(T--) { 79 | scanf("%d%d", &n, &k); 80 | xy.clear(), yx.clear(); 81 | for(int i = 0; i < k; i++) { 82 | int a, b; 83 | scanf("%d%d", &a, &b); 84 | if(invalid(a, b)) continue; 85 | xy[a].push_back(b), yx[b].push_back(a); 86 | } 87 | 88 | tot = 0; 89 | // ensw 90 | int ta[] = {1, 0, 2, 3}; 91 | for(auto i : ta) { 92 | path[1] = dirs[i]; 93 | int a = dx[i], b = dy[i]; 94 | g[a+110][b+110] = 1; 95 | dfs(dx[i], dy[i], i, 2); 96 | g[a+110][b+110] = 0; 97 | } 98 | printf("Found %d golygon(s).\n\n", tot); 99 | } 100 | return 0; 101 | } 102 | 103 | 104 | // give n, k 105 | // find a path from (0,0) to (0,0) 106 | // 4 directions at 1st move, turn left or right at subsequent moves... 107 | // blocked intersections cannot go across 108 | // 109 | // time complexity: 4 * 2 ** (n-1) = 2 ** (n+1) = 2 ** (21) = 2e6 110 | // 111 | // enum left or right: 112 | // turn left or right: even <-> odd 113 | // 0,1,2,3 -> n,e,s,w 114 | // 同一条路线,可以重复经过不能重复访问同一个路口又不说,醉了,uva的题目真的不止一次了。。。 -------------------------------------------------------------------------------- /ch6/uva1103.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | // idea by Rujia Lia 6 | // 字符可以通过拉伸来变换:通过每个字符有多少个洞,来区分字符 7 | // 1. 如何找到一个字符?遇到黑色的pixel 8 | // 2. 如何判断一个字符被检查过了,标记 9 | // 3. 如何判断一个字符有多少个洞? 10 | // 3.1. 记录每个字符的每行的最左像素和最右像素 11 | // 3.2. 遍历每行的字符,做flood fill 12 | // 这个方案是错误的,因为,最左最右像素之间,可能存在外部的白色像素 13 | // 因此,只能利用连通这个特点!!! 14 | // 将一个字复制到新的空白图,然后统计白色的连通分量个数 - 1就是洞的数量 15 | // 注意,还要给整个图片加上白色边框,否则会可能因为没有白色背景而导致白色连通分量统计出错 16 | // 这个正确方案,会展示在uva1103-b.cpp 17 | 18 | // 细化方案 19 | // 1. 通过遍历原图,对于未被遍历的black pixel,做black pixel的flood fill 20 | // flood fill过程中,标记所有4连通的black pixels为2(防止字符被重复识别), 21 | // 记录每一行的最左和最右像素 22 | // 2. 遍历字符的每一行,对于white pixel,做white pixel的flood fill,填充空洞 23 | // 空洞计数加一,标记为2 24 | typedef pair pii; 25 | const int M = 210, N = 210; 26 | int m, w, n, grid[M][N]; 27 | int dx[] = {0, 0, -1, 1}, dy[] = {1, -1, 0, 0}; 28 | unordered_map map; 29 | char arr[6]; 30 | 31 | void dfs(int sx, int sy, bool mark_y) { 32 | if(sx < 0 || sx >= m || sy < 0 || sy >= n) return; 33 | if(grid[sx][sy] != 1) return; 34 | grid[sx][sy] = 2; 35 | if(mark_y) { 36 | if(!map.count(sx)) map[sx] = {sy, sy}; 37 | else { 38 | map[sx].first = min(map[sx].first, sy); 39 | map[sx].second = max(map[sx].second, sy); 40 | } 41 | } 42 | for(int i = 0; i < 4; i++) dfs(sx + dx[i], sy + dy[i], mark_y); 43 | } 44 | 45 | // void fill_hole(int sx, int sy) { 46 | // if(sx < 0 || sx >= m || sy < 0 || sy >= n) return; 47 | // if(grid[sx][sy] != 0) return; 48 | // grid[sx][sy] = 2; 49 | // // for(int dr = -1; dr <= 1; dr++) 50 | // // for(int dc = -1; dc <= 1; dc++) 51 | // // if(dr != 0 || dc != 0) fill_hole(sx + dr, sy + dc); 52 | // for(int i = 0; i < 4; i++) 53 | // fill_hole(sx + dx[i], sy + dy[i]); 54 | // } 55 | 56 | int count_hole() { 57 | int ans = 0; 58 | for(auto& t : map) { 59 | for(int i = t.second.first; i <= t.second.second; i++) 60 | if(grid[t.first][i] == 0) ans++, dfs(t.first, i, false); 61 | } 62 | return ans; 63 | } 64 | 65 | int main(void) { 66 | char line[60]; 67 | arr[1] = 'A', arr[3] = 'J', arr[5] = 'D', arr[4] = 'S', arr[0] = 'W', arr[2] = 'K'; 68 | int cnt = 0; 69 | while(scanf("%d%d\n", &m, &w) != EOF, m) { 70 | n = 4 * w; 71 | for(int i = 0; i < m; i++) { 72 | scanf("%s", line); 73 | printf("%s\n", line); 74 | for(int j = 0; j < w; j++) { 75 | char ch = line[j]; 76 | // printf(j < w - 1 ? "%c" : "%c\n", ch); 77 | int num; 78 | if(isdigit(ch)) num = ch - '0'; 79 | else num = 10 + (ch - 'a'); 80 | // printf(j < w - 1 ? "%d " : "%d\n", num); 81 | for(int k = 3; k >= 0; k--) { 82 | grid[i][4 * j + k] = num & 1; 83 | // printf(k > 0 ? "%d " : "%d\n", grid[i][8 * j + k]); 84 | num >>= 1; 85 | } 86 | } 87 | } 88 | // for(int i = 0; i < m; i++) 89 | // for(int j = 0; j < n; j++) 90 | // printf(j < n - 1 ? "%d " : "%d\n", grid[i][j]); 91 | printf("Case %d: ", ++cnt); 92 | for(int i = 0; i < m; i++) 93 | for(int j = 0; j < n; j++) { 94 | if(grid[i][j] == 1) dfs(i, j, true); 95 | int hole = count_hole(); 96 | // 忘记排序了!!! 97 | printf("%c", arr[hole]); 98 | map.clear(); 99 | } 100 | puts(""); 101 | } 102 | return 0; 103 | } -------------------------------------------------------------------------------- /ch4/uva220.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | // 1 7 | // possible move(s) of current player 8 | // otherwise, hint 9 | // 2 10 | // make a move or change turns if no legal move 11 | // 3 12 | // quit and print 13 | 14 | const int N = 8; 15 | int grid[N + 1][N + 1]; 16 | int bl, wh; 17 | int dx[] = {-1, -1, -1, 0, 1, 1, 1, 0}; 18 | int dy[] = {-1, 0, 1, 1, 1, 0, -1, -1}; 19 | 20 | void print_grid() { 21 | for(int i = 1; i <= N; i++) 22 | for(int j = 1; j <= N; j++) 23 | printf(j < N ? "%c" : "%c\n", grid[i][j]); 24 | } 25 | 26 | bool check_idx(int x, int y) { 27 | return x >= 1 && x <= 8 && y >= 1 && y <= 8; 28 | } 29 | 30 | bool check(int x, int y, char color) { 31 | for(int i = 0; i < 8; i++) { 32 | int tx = x + dx[i], ty = y + dy[i]; 33 | int same = 0, diff = 0; 34 | while(check_idx(tx, ty) && grid[tx][ty] != '-') { 35 | char ch = grid[tx][ty]; 36 | if(ch == color) { 37 | same = 1; break; 38 | } else { 39 | diff++; 40 | } 41 | tx += dx[i], ty += dy[i]; 42 | } 43 | if(diff && same == 1) return true; 44 | } 45 | return false; 46 | } 47 | 48 | void list_move(char color) { 49 | vector> v; 50 | for(int i = 1; i <= N; i++) { 51 | for(int j = 1; j <= N; j++) { 52 | if(grid[i][j] == '-' && check(i, j, color)) 53 | v.push_back({i, j}); 54 | } 55 | } 56 | if(!v.size()) printf("No legal move."); 57 | for(int i = 0; i < v.size(); i++) { 58 | auto t = v[i]; 59 | printf(i > 0 ? " (%d,%d)" : "(%d,%d)", t.first, t.second); 60 | } 61 | puts(""); 62 | } 63 | 64 | void chg_color(char& color) { 65 | color = color == 'B' ? 'W' : 'B'; 66 | } 67 | 68 | bool move(char color, int x, int y) { 69 | bool flag = false; 70 | int cnt = 0; 71 | for(int i = 0; i < 8; i++) { 72 | int tx = x + dx[i], ty = y + dy[i]; 73 | int same = 0, diff = 0; 74 | while(check_idx(tx, ty) && grid[tx][ty] != '-') { 75 | char ch = grid[tx][ty]; 76 | if(ch == color) { 77 | same = 1; break; 78 | } else diff++; 79 | tx += dx[i], ty += dy[i]; 80 | } 81 | if(!(diff && same == 1)) continue; 82 | flag = true; 83 | tx = x + dx[i], ty = y + dy[i]; 84 | do { 85 | grid[tx][ty] = color; 86 | tx += dx[i], ty += dy[i], cnt++; 87 | } while(check_idx(tx, ty) 88 | && grid[tx][ty] != '-' && grid[tx][ty] != color); 89 | } 90 | if(!flag) return false; 91 | if(color == 'B') bl += cnt, wh -= cnt, bl++; 92 | else bl -= cnt, wh += cnt, wh++; 93 | grid[x][y] = color; 94 | return true; 95 | } 96 | 97 | int main(void) { 98 | int w; cin >> w; 99 | for(int i = 0; i < w; i++) { 100 | if(i > 0) puts(""); 101 | bl = 0, wh = 0; 102 | for(int i = 1; i <= N; i++) { 103 | for(int j = 1; j <= N; j++) { 104 | char ch; cin >> ch; 105 | if(ch == 'B') bl++; 106 | else if(ch == 'W') wh++; 107 | grid[i][j] = ch; 108 | } 109 | } 110 | char cmd; 111 | char color; 112 | cin >> color; 113 | while(cin >> cmd, cmd != 'Q') { 114 | if(cmd == 'L') list_move(color); 115 | else if(cmd == 'M') { 116 | int x, y; cin >> x; 117 | y = x % 10, x /= 10; 118 | if(!move(color, x, y)) 119 | chg_color(color), move(color, x, y); 120 | chg_color(color); 121 | printf("Black - %2d White - %2d\n", bl, wh); 122 | } 123 | } 124 | print_grid(); 125 | } 126 | return 0; 127 | } -------------------------------------------------------------------------------- /ch4/uva1589.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | // 对于每组问题: 10 | // 枚举black general能走到的有效位置(x, y) 11 | // 枚举全部red pieces,判断是否能走到(x, y) 12 | 13 | // capture rules: 14 | // G - general: 15 | // no pieces between 2 general 16 | // y1 == y2 && (x1 - 1 ... x2 + 1, y1)上没有任何pieces 17 | // R - chariot: 18 | // (x1 == x2 && y1 < y2 && (x1, y1 + 1 ... y2 - 1)上没有任何pieces) 19 | // || (y1 == y2 && x1 < x2 && (x1 + 1 ... x2 - 1, y1)上没有任何pieces) 20 | // C - cannon: 21 | // (x1 == x2 && y1 < y2 && (x1, y1 + 1 ... y2 - 1)只有1个piece) 22 | // || (y1 == y2 && x1 < x2 && (x1 + 1 ... x2 - 1, y1)只有1个piece) 23 | // H - horse: 24 | // 枚举(最多8个)有效位置,注意蹩马腿 25 | 26 | typedef pair pii; 27 | 28 | typedef bool(*check_fp)(int, int, int, int); 29 | 30 | const int N = 11; 31 | char grid[N][N]; 32 | vector v; 33 | unordered_map fn_map; 34 | 35 | bool check_idx(int x, int y) { 36 | return x >= 1 && x <= 10 && y >= 1 && y <= 9; 37 | } 38 | 39 | bool check_g_idx(int x, int y) { 40 | return x >= 1 && x <= 3 && y >= 4 && y <= 6; 41 | } 42 | 43 | bool check_g(int x, int y, int gx, int gy) { 44 | if(x == gx && y == gy) return false; 45 | if(y != gy) return false; 46 | for(int i = gx + 1; i <= x - 1; i++) 47 | if(grid[i][y]) return false; 48 | return true; 49 | } 50 | 51 | bool check_r(int x, int y, int gx, int gy) { 52 | if(x == gx && y == gy) return false; 53 | if(x == gx) { 54 | int from = min(y, gy) + 1, to = max(y , gy) - 1; 55 | for(int j = from; j <= to; j++) 56 | if(grid[x][j]) return false; 57 | return true; 58 | } 59 | if(y == gy) { 60 | int from = min(x, gx) + 1, to = max(x, gx) - 1; 61 | for(int i = from; i <= to; i++) 62 | if(grid[i][y]) return false; 63 | return true; 64 | } 65 | return false; 66 | } 67 | 68 | bool check_c(int x, int y, int gx, int gy) { 69 | if(x == gx && y == gy) return false; 70 | if(x == gx) { 71 | int from = min(y, gy) + 1, to = max(y , gy) - 1; 72 | int cnt = 0; 73 | for(int j = from; j <= to && cnt <= 1; j++) 74 | if(grid[x][j]) cnt++; 75 | if(cnt == 1) return true; 76 | } 77 | if(y == gy) { 78 | int from = min(x, gx) + 1, to = max(x, gx) - 1; 79 | int cnt = 0; 80 | for(int i = from; i <= to && cnt <= 1; i++) 81 | if(grid[i][y]) cnt++; 82 | if(cnt == 1) return true; 83 | } 84 | return false; 85 | } 86 | 87 | bool check_h(int x, int y, int gx, int gy) { 88 | if(x == gx && y == gy) return false; 89 | // up, right, down, left 90 | int dy[8] = {-1, 1, 2, 2, 1, -1, -2, -2}; 91 | int dx[8] = {-2, -2, -1, 1, 2, 2, 1, -1}; 92 | for(int i = 0; i < 8; i++) { 93 | int tx = x + dx[i], ty = y + dy[i]; 94 | if(!check_idx(tx, ty)) continue; 95 | if(i / 2 == 0 && grid[x - 1][y]) continue; 96 | else if(i / 2 == 1 && grid[x][y + 1]) continue; 97 | else if(i / 2 == 2 && grid[x + 1][y]) continue; 98 | else if(i / 2 == 3 && grid[x][y - 1]) continue; 99 | if(tx == gx && ty == gy) return true; 100 | } 101 | return false; 102 | } 103 | 104 | bool check_mate(int x, int y) { 105 | for(auto t : v) { 106 | int tx = t.first, ty = t.second; 107 | char type = grid[tx][ty]; 108 | if((*fn_map[type])(tx, ty, x, y)) return true; 109 | } 110 | return false; 111 | } 112 | 113 | 114 | int main(void) { 115 | fn_map['G'] = check_g; 116 | fn_map['H'] = check_h; 117 | fn_map['R'] = check_r; 118 | fn_map['C'] = check_c; 119 | while(true) { 120 | int n, x , y; cin >> n >> x >> y; 121 | if(!x) break; 122 | memset(grid, 0, sizeof grid); 123 | v.clear(); 124 | for(int i = 0; i < n; i++) { 125 | char type; 126 | int tx, ty; 127 | cin >> type >> tx >> ty; 128 | grid[tx][ty] = type; 129 | v.push_back({tx, ty}); 130 | } 131 | int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0}; 132 | bool flag = true; 133 | for(int i = 0; i < 4; i++) { 134 | int tx = x + dx[i], ty = y + dy[i]; 135 | if(check_g_idx(tx, ty) && !check_mate(tx, ty)) { 136 | flag = false; break; 137 | } 138 | } 139 | if(flag) printf("YES\n"); 140 | else printf("NO\n"); 141 | } 142 | return 0; 143 | } -------------------------------------------------------------------------------- /ch6/uva816.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | struct State { 9 | int x; 10 | int y; 11 | int dir; 12 | }; 13 | 14 | const int N = 10; 15 | bool st[N][N][4][3]; 16 | int dist[N][N][4]; 17 | State pre[N][N][4]; 18 | State entra, dest; 19 | char maze_name[30]; 20 | 21 | const string dirs = "NESW"; 22 | const string turns = "FLR"; 23 | 24 | int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 25 | 26 | int dir_id(char ch) { 27 | for(int i = 0; i < 4; i++) 28 | if(dirs[i] == ch) return i; 29 | return -1; 30 | } 31 | 32 | int turn_id(char ch) { 33 | for(int i = 0; i < 3; i++) 34 | if(turns[i] == ch) return i; 35 | return -1; 36 | } 37 | 38 | State trans(const State& u, int turn) { 39 | int dir = u.dir; 40 | if(turn == 1) dir = (dir - 1 + 4) % 4; 41 | if(turn == 2) dir = (dir + 1) % 4; 42 | return State {u.x + dx[dir], u.y + dy[dir], dir}; 43 | } 44 | 45 | void print_ans() { 46 | vector v; 47 | auto t = dest; 48 | for(;;) { 49 | v.push_back(t); 50 | if(!dist[t.x][t.y][t.dir]) break; 51 | t = pre[t.x][t.y][t.dir]; 52 | } 53 | v.push_back(entra); 54 | for(int j = v.size() - 1; j >= 0;) { 55 | printf(" "); 56 | for(int i = 0; i < 10 && j >= 0; i++, j--) { 57 | auto t = v[j]; 58 | printf(" (%d,%d)", t.x, t.y); 59 | } 60 | puts(""); 61 | } 62 | } 63 | 64 | bool inside(int r, int c) { 65 | return r >= 1 && r <= 9 && c >= 1 && c <= 9; 66 | } 67 | 68 | bool solve() { 69 | queue q; 70 | memset(dist, -1, sizeof(dist)); 71 | auto u = trans(entra, turn_id('F')); 72 | pre[u.x][u.y][u.dir] = entra; 73 | // 为什么不将entra设置为0呢?因为entra没被搜索过,实际上第一个被搜索的状态是 74 | // tran(entra, turn_id('F')) 75 | // 而且,如果将dist of entra设置为0,那么dist后面可能会被覆盖 76 | dist[u.x][u.y][u.dir] = 0; 77 | q.push(u); 78 | while(q.size()) { 79 | auto u = q.front(); q.pop(); 80 | if(u.x == dest.x && u.y == dest.y) { 81 | dest.dir = u.dir; 82 | return true; 83 | } 84 | for(int i = 0; i < 3; i++) { 85 | if(!st[u.x][u.y][u.dir][i]) continue; 86 | auto v = trans(u, i); 87 | // dist不能改成bool类型,因为同一个点可能会被经过好多次 88 | // 利用pre求路线时,无法判断 89 | if(dist[v.x][v.y][v.dir] < 0 && inside(v.x, v.y)) { 90 | dist[v.x][v.y][v.dir] = dist[u.x][u.y][u.dir] + 1; 91 | pre[v.x][v.y][v.dir] = u; 92 | q.push(v); 93 | } 94 | } 95 | } 96 | return false; 97 | } 98 | 99 | 100 | int main(void) { 101 | while(scanf("%s", maze_name), strcmp(maze_name, "END") != 0) { 102 | int x, y; char str[5]; 103 | memset(st, 0, sizeof(st)); 104 | scanf("%d%d%s", &x, &y, str); 105 | entra = State{x, y, dir_id(str[0])}; 106 | scanf("%d%d", &x, &y); 107 | dest = {x, y, 0}; 108 | while(scanf("%d", &x), x) { 109 | scanf("%d", &y); 110 | while(scanf("%s", str), strcmp(str, "*") != 0) { 111 | int dir = dir_id(str[0]); 112 | for(int i = 1; i < strlen(str); i++) { 113 | st[x][y][dir][turn_id(str[i])] = true; 114 | } 115 | } 116 | } 117 | printf("%s\n", maze_name); 118 | if(solve()) print_ans(); 119 | else puts(" No Solution Possible"); 120 | } 121 | return 0; 122 | } 123 | 124 | // 整个迷宫可以被视作一张图,intersection就是图中的节点 125 | // 显然,这是一张无权图,可以用BFS求最短路 126 | // 但是,问题在于这张图上的点,如果只用坐标来标识是不够的 127 | // 因为,出方向被入方向所决定,点之间的关系是动态的,不是静态的 128 | // 如何解决这个问题呢? 129 | // 根据题目,我们知道,从某个方向进入某个点,它必然从某个固定的方向进入固定的点 130 | // 换言之,如果我们将(r,c,dir)看作一个状态,那么它的状态转移路径是确定的 131 | // 所以,我们可以使用BFS遍历这些状态,找到状态转移的最短路径 132 | 133 | // while !q.empty 134 | // for node in q 135 | // if q is end, break 136 | // for 3 dirs 137 | // if d[node][nextnode] enque 138 | 139 | // dispatch uni-id for each dirs 140 | // struct Node {int r; int c; int dir;} 141 | // st[r][c][dir] whether (r,c) can go from dir 142 | // how to calculate next node ? 143 | // 144 | // while !q.emtpy 145 | // for node in q 146 | // for dir in 3dirs 147 | // if(!st[node.r][node.c][node.dir][dir]) continue; 148 | // nextnode = calnext(node, dir) 149 | // if(can_reach(nextnode.r, nextnode.c) 150 | // && d[nextnode.r][nextnode.c][nextnode.dir] < 0) 151 | // nd = d + 1; 152 | // mark the pre node; 153 | // enque 154 | 155 | // 这个方案是有缺陷的,因为起点可能被经过不止一次,所以用bool类型的visited的话,无法分辨是第几次 -------------------------------------------------------------------------------- /ch7/uva1601.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | const int maxn = 20; 11 | pair pos[maxn * maxn]; 12 | vector map[maxn * maxn]; 13 | unordered_map dist; 14 | int id[maxn][maxn]; 15 | int start, dest; 16 | int dx[] = {0, 0, -1, 1, 0}, dy[] = {-1, 1, 0, 0, 0}; 17 | 18 | bool is_conflict(int a, int b, int na, int nb) { 19 | return na == nb || (a == nb && b == na); 20 | } 21 | 22 | int bfs() { 23 | queue q; 24 | dist.clear(); 25 | q.push(start); 26 | dist[start] = 0; 27 | while(q.size()) { 28 | int t = q.front(); q.pop(); 29 | // id -> pos, pos -> npos, npos -> nid 30 | int a = t & 255, b = (t >> 8) & 255, c = (t >> 16) & 255; 31 | // printf("%d %d %d\n", a, b, c); 32 | for(int i = 0; i < map[a].size(); i++) { 33 | int na = map[a][i]; 34 | for(int j = 0; j < map[b].size(); j++) { 35 | int nb = map[b][j]; 36 | if(is_conflict(a, b, na, nb)) continue; 37 | for(int k = 0; k < map[c].size(); k++) { 38 | int nc = map[c][k]; 39 | if(is_conflict(a, c, na, nc)) continue; 40 | if(is_conflict(b, c, nb, nc)) continue; 41 | // printf("%d %d %d\n", na, nb, nc); 42 | int next = 0; 43 | next |= na, next |= (nb << 8), next |= (nc << 16); 44 | if(dist.count(next)) continue; 45 | if(next == dest) return dist[t] + 1; 46 | dist[next] = dist[t] + 1; 47 | q.push(next); 48 | } 49 | } 50 | } 51 | // printf("\n"); 52 | } 53 | return -1; 54 | } 55 | 56 | int main(void) { 57 | #ifdef LOCAL 58 | freopen("uva1601.in", "r", stdin); 59 | freopen("uva1601.out", "w", stdout); 60 | #endif 61 | 62 | int w, h, n; 63 | char g[20][20]; 64 | while(scanf("%d%d%d", &w, &h, &n), n) { 65 | scanf("\n"); 66 | for(int i = 0; i < h; i++) fgets(g[i], 20, stdin); 67 | // for(int i = 0; i < h; i++) 68 | // printf("%s", g[i]); 69 | int cnt = 0; 70 | for(int i = 0; i < h; i++) { 71 | for(int j = 0; j < w; j++) { 72 | if(g[i][j] != '#') 73 | pos[cnt] = {i, j}, id[i][j] = cnt++; 74 | } 75 | } 76 | start = dest = 0; 77 | for(int i = 0; i < cnt; i++) { 78 | map[i].clear(); 79 | int a = pos[i].first, b = pos[i].second; 80 | for(int j = 0; j < 5; j++) { 81 | int ta = a + dx[j], tb = b + dy[j]; 82 | if(ta < 0 || ta >= h || tb < 0 || tb >= w) continue; 83 | int ch = g[ta][tb], tid = id[ta][tb]; 84 | if(ch == '#') continue; 85 | if(islower(ch)) start |= (tid << (ch - 'a') * 8); 86 | if(isupper(ch)) dest |= (tid << (ch - 'A') * 8); 87 | map[i].push_back(tid); 88 | } 89 | } 90 | if(n <= 2) map[cnt].push_back(cnt), start |= cnt << 16, dest += cnt << 16, cnt++; 91 | if(n <= 1) map[cnt].push_back(cnt), start |= cnt << 8, dest += cnt << 8, cnt++; 92 | printf("%d\n", bfs()); 93 | } 94 | return 0; 95 | } 96 | 97 | // for this problem, 98 | // every ghost has a start point and an end point. 99 | // our job is to move the ghost with least steps 100 | // let notice some crucial detail: 101 | // 1. treat all ghosts' position as a whole, it turns to be a state search problem 102 | // but the problem is, every ghost 256 status, all ghost may have 256 ** 3 status 103 | // and each status has 5 ** 3 which is 125 possiblity of next status, 104 | // so the time complexity whould be 1e8 * 1e2, 1e10 will exceed the 1s time limitation. 105 | // conclusion 1: we need to reduce the searched status 106 | // 107 | // 2. Any 2*2 area on any map has at least one sharp 108 | // There are 1/4 sharps, if we ignore them, all ghost may have 144 ** 3 status 109 | // which is totallly 3e6, the time complexity is effectively decreased 110 | // 111 | // 3. All corridor cells in a map are connected 112 | // so we can ignore the sharps, without affect the result 113 | // 114 | // untill now, we can confirm that the state space is mostly 64 ** 3 * 125 = 3e8 115 | // and of course we can cut the branch when the ghost movement is illegal to decrease the state space again 116 | // 117 | // now we should consider how to model the status and the grid 118 | // lets see the valid state transition rule: 119 | // 1. No more than one ghost occupies one position at the end of the step. 120 | // 2. No pair of ghosts exchange their positions one another in the step. 121 | // we should check whether they occupy the same positon or swap position 122 | // so how to model the position? give them an id or use the (x,y) diretly? 123 | // firstly, we must keep the (x,y) in order to calculate the move. 124 | // secondly, we can assign an id to each position so we can treat the grid as a map 125 | // contains of nodes with id and edge 126 | // 127 | // 1. we assign each pos an id and preprocess the connect corridor cells to a connected map 128 | // 2. we consider the pos of (at most) 3 ghosts as a whole, since there are at most 144 status 129 | // we can store the id into a 8 bit uint, so we can store pos of 3 ghost into a 32 bit int 130 | // 3. the valid transition rule : for ghost a to na, ghost b to nb, na != nb && (a != nb || b != na) 131 | // 4. for state transition consisitency, we will always have 3 ghost, add fake ghost if less than 3. 132 | 133 | // for each case: 134 | // give the empty space an id 135 | // for each node , add an edge if it can connect to 4 neighbours 136 | // while add edge, save the pos of ghost and the end point 137 | // if ghosts is less than 3, than add fake ghost, assign each an id and add it to the map 138 | // use bfs search to travase states 139 | 140 | // compare to Rujia Liu's solutions: a struct can be split to several arrays each represent a field 141 | // what i learn from this question: when necessary or state transitions are complicated, 142 | // we can build a implict graph, assign each state an id, transform state transition to graph traversal -------------------------------------------------------------------------------- /ch7/uva1601-b.cpp: -------------------------------------------------------------------------------- 1 | #define LOCAL 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | const int maxn = 20; 11 | pair pos[maxn * maxn]; 12 | vector map[maxn * maxn]; 13 | int id[maxn][maxn]; 14 | int start, dest; 15 | int dx[] = {0, 0, -1, 1, 0}, dy[] = {-1, 1, 0, 0, 0}; 16 | 17 | bool is_conflict(int a, int b, int na, int nb) { 18 | return na == nb || (a == nb && b == na); 19 | } 20 | // 双向广搜版本 21 | int search(queue& q, queue& qb 22 | , unordered_map& dist, unordered_map& distb) { 23 | int t = q.front(); q.pop(); 24 | // id -> pos, pos -> npos, npos -> nid 25 | int a = t & 255, b = (t >> 8) & 255, c = (t >> 16) & 255; 26 | // printf("%d %d %d\n", a, b, c); 27 | for(int i = 0; i < map[a].size(); i++) { 28 | int na = map[a][i]; 29 | for(int j = 0; j < map[b].size(); j++) { 30 | int nb = map[b][j]; 31 | if(is_conflict(a, b, na, nb)) continue; 32 | for(int k = 0; k < map[c].size(); k++) { 33 | int nc = map[c][k]; 34 | if(is_conflict(a, c, na, nc)) continue; 35 | if(is_conflict(b, c, nb, nc)) continue; 36 | // printf("%d %d %d\n", na, nb, nc); 37 | int next = 0; 38 | next |= na, next |= (nb << 8), next |= (nc << 16); 39 | if(dist.count(next)) continue; 40 | if(distb.count(next)) return dist[t] + distb[next] + 1; 41 | dist[next] = dist[t] + 1; 42 | q.push(next); 43 | } 44 | } 45 | } 46 | return -1; 47 | } 48 | 49 | int bfs() { 50 | queue qa; 51 | queue qb; 52 | unordered_map dista; 53 | unordered_map distb; 54 | qa.push(start); 55 | qb.push(dest); 56 | dista[start] = 0; 57 | distb[dest] = 0; 58 | while(qa.size() || qb.size()) { 59 | int ans; 60 | if(qa.size() && (ans = search(qa, qb, dista, distb)) != -1) return ans; 61 | if(qb.size() && (ans = search(qb, qa, distb, dista)) != -1) return ans; 62 | } 63 | return -1; 64 | } 65 | 66 | int main(void) { 67 | #ifdef LOCAL 68 | freopen("uva1601.in", "r", stdin); 69 | freopen("uva1601.out", "w", stdout); 70 | #endif 71 | 72 | int w, h, n; 73 | char g[20][20]; 74 | while(scanf("%d%d%d", &w, &h, &n), n) { 75 | scanf("\n"); 76 | for(int i = 0; i < h; i++) fgets(g[i], 20, stdin); 77 | // for(int i = 0; i < h; i++) 78 | // printf("%s", g[i]); 79 | int cnt = 0; 80 | for(int i = 0; i < h; i++) { 81 | for(int j = 0; j < w; j++) { 82 | if(g[i][j] != '#') 83 | pos[cnt] = {i, j}, id[i][j] = cnt++; 84 | } 85 | } 86 | start = dest = 0; 87 | for(int i = 0; i < cnt; i++) { 88 | map[i].clear(); 89 | int a = pos[i].first, b = pos[i].second; 90 | for(int j = 0; j < 5; j++) { 91 | int ta = a + dx[j], tb = b + dy[j]; 92 | if(ta < 0 || ta >= h || tb < 0 || tb >= w) continue; 93 | int ch = g[ta][tb], tid = id[ta][tb]; 94 | if(ch == '#') continue; 95 | if(islower(ch)) start |= (tid << (ch - 'a') * 8); 96 | if(isupper(ch)) dest |= (tid << (ch - 'A') * 8); 97 | map[i].push_back(tid); 98 | } 99 | } 100 | if(n <= 2) map[cnt].push_back(cnt), start |= cnt << 16, dest += cnt << 16, cnt++; 101 | if(n <= 1) map[cnt].push_back(cnt), start |= cnt << 8, dest += cnt << 8, cnt++; 102 | printf("%d\n", bfs()); 103 | } 104 | return 0; 105 | } 106 | 107 | // for this problem, 108 | // every ghost has a start point and an end point. 109 | // our job is to move the ghost with least steps 110 | // let notice some crucial detail: 111 | // 1. treat all ghosts' position as a whole, it turns to be a state search problem 112 | // but the problem is, every ghost 256 status, all ghost may have 256 ** 3 status 113 | // and each status has 5 ** 3 which is 125 possiblity of next status, 114 | // so the time complexity whould be 1e8 * 1e2, 1e10 will exceed the 1s time limitation. 115 | // conclusion 1: we need to reduce the searched status 116 | // 117 | // 2. Any 2*2 area on any map has at least one sharp 118 | // There are 1/4 sharps, if we ignore them, all ghost may have 144 ** 3 status 119 | // which is totallly 3e6, the time complexity is effectively decreased 120 | // 121 | // 3. All corridor cells in a map are connected 122 | // so we can ignore the sharps, without affect the result 123 | // 124 | // untill now, we can confirm that the state space is mostly 64 ** 3 * 125 = 3e8 125 | // and of course we can cut the branch when the ghost movement is illegal to decrease the state space again 126 | // 127 | // now we should consider how to model the status and the grid 128 | // lets see the valid state transition rule: 129 | // 1. No more than one ghost occupies one position at the end of the step. 130 | // 2. No pair of ghosts exchange their positions one another in the step. 131 | // we should check whether they occupy the same positon or swap position 132 | // so how to model the position? give them an id or use the (x,y) diretly? 133 | // firstly, we must keep the (x,y) in order to calculate the move. 134 | // secondly, we can assign an id to each position so we can treat the grid as a map 135 | // contains of nodes with id and edge 136 | // 137 | // 1. we assign each pos an id and preprocess the connect corridor cells to a connected map 138 | // 2. we consider the pos of (at most) 3 ghosts as a whole, since there are at most 144 status 139 | // we can store the id into a 8 bit uint, so we can store pos of 3 ghost into a 32 bit int 140 | // 3. the valid transition rule : for ghost a to na, ghost b to nb, na != nb && (a != nb || b != na) 141 | // 4. for state transition consisitency, we will always have 3 ghost, add fake ghost if less than 3. 142 | 143 | // for each case: 144 | // give the empty space an id 145 | // for each node , add an edge if it can connect to 4 neighbours 146 | // while add edge, save the pos of ghost and the end point 147 | // if ghosts is less than 3, than add fake ghost, assign each an id and add it to the map 148 | // use bfs search to travase states -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 《算法竞赛入门经典》第2版 2 | 目前正在完成最低要求的部分 3 | 4 | 目前做到了**第7章**,这个目录会慢慢同步更新,并且不定期总结每章的知识点。 5 | 6 | 对于每一章,暂时只做书中声明必要的部分。 7 | 8 | ### 第三章 数组与字符串(例题太简单,没做。。。) 9 | 10 | - [习题3-1,得分(Score),uva1585](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/arrayandstring/uva1585.cpp) 11 | - [习题3-2,分子量(Molar Mass),uva1586](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/arrayandstring/uva1586.cpp) 12 | - [习题3-3,数数字(Digit Counting),uva1225](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/arrayandstring/uva1225.cpp) 13 | - [习题3-4,周期串(Periodic Strings),uva455](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/arrayandstring/uva455.cpp) 14 | - [习题3-5,谜题(Puzzle),uva227](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/arrayandstring/uva227.cpp) 15 | - 习题3-6,纵横字谜的答案(Crossword Answers),uva232 16 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/arrayandstring/uva232-1.cpp) 17 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/arrayandstring/uva232-2.cpp) 18 | - [习题3-7,DNA序列(DNA Consensus String),uva1368](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/arrayandstring/uva1368.cpp) 19 | - [习题3-8,循环小数(Repeating Decimals),uva202](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/arrayandstring/uva202.cpp) 20 | 21 | ### 第四章 函数与递归 22 | 23 | - [例题4-1,古老的密码(Ancient Cipher),uva1339](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch4/uva1339.cpp) 24 | - [例题4-2,刽子手游戏(Hangman Game),uva489](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch4/uva489.cpp) 25 | - [例题4-3,救济金发放(The Dole Queue),uva133](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch4/uva133.cpp) 26 | - [例题4-4,信息解码(Message Decoding),uva213](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch4/uva213.cpp) 27 | - [习题4-1,象棋(Xiangqi),uva1589](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch4/uva1589.cpp) 28 | - [习题4-2,正方形(Squares),uva201](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch4/uva201.cpp) 29 | - [习题4-3,黑白棋(Othello),uva220](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch4/uva220.cpp) 30 | 31 | ### 第五章 C++与STL入门 32 | 33 | - [例题5-1,大理石在哪儿(Where is the Marble?),uva10474](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva10474.cpp) 34 | - [例题5-2,木块问题(The Blocks Problem),uva101](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva101.cpp) 35 | - [例题5-3,安迪的第一个字典(Andy's First Dictinonary),uva10815](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva10815.cpp) 36 | - [例题5-4,反片语(Ananagrams),uva156](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva156.cpp) 37 | - [例题5-5,集合栈计算机(The SetStack Computer),uva12096](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva12096.cpp) 38 | - [例题5-6,团体队列(Team Queue),uva540](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva540.cpp) 39 | - [例题5-7,丑数(Ugly Numbers),uva136](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva136.cpp) 40 | - [例题5-8,Unix ls命令(Unix ls),uva400](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva400.cpp) 41 | - [例题5-9,数据库(Database),uva1592](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva1592.cpp) 42 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva1592.cpp) 43 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva1592-b.cpp) 44 | - [习题5-1,代码对齐(Alignment of Code),uva1593](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva1593.cpp) 45 | - [习题5-2,Ducci序列(Ducci Sequence),uva1594](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva1594.cpp) 46 | - [习题5-3,卡片游戏(Throwing cards away),uva10935](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva10935.cpp) 47 | - [习题5-4,交换学生(Foreign Exchange),uva10763](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva10763.cpp) 48 | - [习题5-5,复合词(Compound Words),uva10391](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva10391.cpp) 49 | - [习题5-6,对称轴(Symmetry),uva1595](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva1595.cpp) 50 | - [习题5-7,打印队列(Printer Queue),uva12100](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva12100.cpp) 51 | - [习题5-8,图书管理系统(Borrowers),uva230](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch5/uva230.cpp) 52 | 53 | ### 第六章 数据结构基础 54 | 55 | - 例题6-1,并行程序模拟(Concurrency Simulator),uva210 56 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva210.cpp) 57 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva210-b.cpp) 58 | - [解答3](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva210-c.cpp) 59 | - [例题6-2,铁轨(Rails),uva514](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva514.cpp) 60 | - [例题6-3,矩阵链乘(Matrix Chain Multiplication),uva442](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva442.cpp) 61 | - 例题6-4,破损的键盘(又名:悲剧文本)(Broken Keyboard(a.k.a Beiju Text)),uva11988 62 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva11988.cpp) 63 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva11988-b.cpp) 64 | - [例题6-5,移动盒子(Box in a Line),uva12657](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva12657.cpp) 65 | - 例题6-6,小球下落(Dropping Balls),uva679 66 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva679.cpp) 67 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva679-b.cpp) 68 | - 例题6-7,树的层次遍历(Trees on the Level),uva122 69 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva122.cpp) 70 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva210-b.cpp) 71 | - [解答3](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva122-c.cpp) 72 | - [例题6-8,树(Tree),uva548](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva548.cpp) 73 | - [例题6-9,天平(Not so Mobile),uva839](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva839.cpp) 74 | - [例题6-10,下落的树叶(The Falling Leaves),uva699](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva699.cpp) 75 | - 例题6-11,四分树(Quadtrees),uva297 76 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva297.cpp) 77 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva297-b.cpp) 78 | - [例题6-12,油田(Oil Deposits),uva572](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva572.cpp) 79 | - 例题6-13,古代象形符号(Ancient Messages),uva1103 80 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva1103.cpp) 81 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva1103-b.cpp) 82 | - [解答3](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva1103-c.cpp) 83 | - 例题6-14,Abbott的复仇(Abbott's Revenge),uva816 84 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva816.cpp) 85 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva816-b.cpp) 86 | - [例题6-15,给任务排序(Ordering Tasks),uva10305](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva10305.cpp) 87 | - 例题6-16,单词(Play on Words),uva10129 88 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva10129.cpp) 89 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva10129-b.cpp) 90 | - [例题6-17,看图写树(Undraw the Trees),uva10562](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva10526.cpp) 91 | - [例题6-19,自组合(Self-Assembly),uva1572](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva1572.cpp) 92 | - [例题6-20,理想路径(Ideal Path),uva1599](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva1599.cpp) 93 | - [例题6-21,系统依赖(System Dependencies),uva506](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva506.cpp) 94 | - [习题6-1,平衡的括号(Parentheses Balance),uva673](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva673.cpp) 95 | - [习题6-2,S树(S-Trees),uva712](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva712.cpp) 96 | - [习题6-3,二叉树重建(Tree Recovery),uva536](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva536.cpp) 97 | - [习题6-4,骑士的移动(Knight Moves),uva439](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva439.cpp) 98 | - 习题6-5,巡逻机器人(Patrol Robot),uva1600 99 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva1600.cpp) 100 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva1600-b.cpp) 101 | - [习题6-6,修改天平(Equilibrium Mobile),uva12166](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva12166.cpp) 102 | - [习题6-7,Petri网模拟(Petri Net Simulation),uva804](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva804.cpp) 103 | - [习题6-8,空间结构(Spatial Structures),uva806](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch6/uva806.cpp) 104 | 105 | ### 第七章 暴力求解法 106 | 107 | - [例题7-1,uva725,Division](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva725.cpp) 108 | - [例题7-2,uva11059,Maximum Product](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva11059.cpp) 109 | - [例题7-3,uva10976,Fractions Again?!](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva10976.cpp) 110 | - [例题7-4,uva524,Prime Ring Problem](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva524.cpp) 111 | - [例题7-5,uva129,Krypton Factor](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva129.cpp) 112 | - [例题7-6,uva140,Bandwidth](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva140.cpp) 113 | - [例题7-7,uva1354,Mobile Computing](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva1354.cpp) 114 | - [例题7-8,uva10603,Fill](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva10603.cpp) 115 | - 例题7-9,uva1601,The Morning after Halloween 116 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva1601.cpp) 117 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva1601-b.cpp) 118 | - [例题7-10,uva11212,Editing a Book](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva11212.cpp) 119 | - [例题7-11,uva12325,Zombie's Treasure Chest](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva12325.cpp) 120 | - [例题7-12,uva1343,The Rotation Game](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva1343.cpp) 121 | - [例题7-13,UVA1374,Power Calculus](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva1374.cpp) 122 | - 例题7-14,uva1602,Lattice Animals,跳过。。。 123 | - 例题7-15,uva1603,Square Destroyer,跳过。。。 124 | - [习题7-1,uva208,Firetruck](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva208.cpp) 125 | - 习题7-2,uva225,Golygons 126 | - [解答1](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva225.cpp) 127 | - [解答2](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva225-b.cpp) 128 | - [解答3](https://github.com/iltonmi/iltonmi-aoapc-bac2nd/blob/master/ch7/uva225-c.cpp) 129 | 130 | 未完待续。。。 --------------------------------------------------------------------------------