08年区域赛北京赛区 http://poj.org/searchproblem?field=source&key=Beijing+2008
POJ 3921 Destroying the bus stations
题目还是比较难的,当时的榜似乎只有4/25的通过/提交,其实题目数据很水。学长转换模型写了网络流求最小割,可以AC,不过自己造了个数据推翻了正确性。我写了个很挫的bfs套bfs,外层是最小的删除点数,内层是求最短路,数据很水可以AC。但比较蛋疼的在于bfs耗内存,而且队列中的点数是阶乘的复杂度,面对学长的数据直接跪了。
正解是迭代加深搜索,逐步加大删除的点数,然后bfs求最短路。虽然面对强数据还是弱,但是是我已知的最优解了。
额,好像漏了个关键的地方了。我们要删的点肯定是当前最短路上的点,所以依次枚举最短路上的点删除,如果都不行,就删除新图中的最短路上的点,这就是一个递归的过程。
代码比较挫就不贴了。
POJ 3922 A simple stone game
很厉害的博弈,k倍动态减法。还没研究。。
POJ 3923 Ugly Windows
就是个小模拟。开始忘记了一个小框完全覆盖大框的情况。然后还有一种容易忽略的情况是,被遮住只剩下一行。我是判断能不能从一个点出发再走回到自己,然后遍历左上到右下,没有其他框的代表字母即可。
1 #include<cstdio>
2 #include<iostream>
3 #include<cstring>
4 #include<cmath>
5 #include<algorithm>
6 #include<cstdlib>
7 #include<set>
8 #include<map>
9 #include<queue>
10 #include<ctime>
11 #include<string>
12 using namespace std;
13
14 struct point{
15 int r, c;
16 } st[100];
17 bool vis[300][300];
18 int anssize, n, m;
19 int ct[100];
20 char str[300][300], ans[100];
21 int dr[] = {1, -1, 0, 0},
22 dc[] = {0, 0, 1, -1};
23 int lx[30],
24 ly[30];
25 bool check(int id)
26 {
27 int cnt = 0;
28 int rr = st[id].r, cc = st[id].c;
29 int start = rr, end = cc;
30 bool flag = false;
31 while(cnt < ct[id]){
32 //printf("%d %d %d\n", rr, cc, cnt);
33 vis[rr][cc] = true;
34 cnt ++;
35 int i, nr, nc;
36 for (i = 0; i < 4; i++){
37 nr = rr + dr[i],
38 nc = cc + dc[i];
39 if (nr > n-1 || nc > m-1 || nr < 0 || nc < 0)
40 continue;
41 if (cnt == ct[id] && nr == start && nc == end) flag = true;
42 if (vis[nr][nc] || str[nr][nc] - ‘A‘ != id) continue;
43 break;
44 }
45 if (i == 4) break;
46 else{
47 rr = nr;
48 cc = nc;
49 }
50 }
51 bool flag2 = true;
52 char tmp = id + ‘A‘;
53 for (int i = lx[id]; i <= start; i++){
54 if (!flag2) break;
55 for (int j = ly[id]; j <= end; j++)
56 if (str[i][j] != ‘.‘ && str[i][j] != tmp){
57 flag2 = false;
58 break;
59 }
60 }
61 if (cnt == ct[id] && flag && flag2) return true;
62 else return false;
63 }
64 int main()
65 {
66 while(scanf("%d %d", &n, &m) && (n+m))
67 {
68 memset(st, 0, sizeof(st));
69 memset(vis, false, sizeof(vis));
70 memset(ct, 0, sizeof(ct));
71 for (int i = 0; i < n; i++){
72 scanf("%s", str[i]);
73 for (int j = 0; j < m; j++){
74 if (str[i][j] != ‘.‘){
75 ct[str[i][j]-‘A‘] ++;
76 if (ct[str[i][j]-‘A‘] == 1){
77 lx[str[i][j]-‘A‘] = i;
78 ly[str[i][j]-‘A‘] = j;
79 }
80 st[str[i][j]-‘A‘].r = i;
81 st[str[i][j]-‘A‘].c = j;
82 }
83 }
84 }
85 anssize = 0;
86 for (int i = 0; i < 26; i++)
87 if (ct[i]){
88 if (check(i)){
89 ans[anssize++] = i + ‘A‘;
90 }
91 }
92 ans[anssize] = ‘\0‘;
93 printf("%s\n", ans);
94 }
95 return 0;
96 }
POJ 3924 Tornado
貌似是最难的一道,计算几何,还没做。
POJ 3925 Minimal Ratio Tree
乍一看很厉害,其实点数很少,直接枚举所选的点,然后就是求最小生成树了。开始读错题,以为答案是升序排列,字典序最大的,多了很多无用代码和一个WA。。然后读入没读好,后面懒得改就写了手很生的prim。。代码挺挫。。
1 #include<cstdio>
2 #include<cmath>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6
7 const double eps = 1e-6;
8 int n, m;
9 bool vis[20];
10 int a[20], d[20];
11 bool use[20];
12 double bestratio;
13 int edgesum, pointsum;
14 int e[20][20];
15 int tmpans[20], ans[20];
16 void dfs(int dep, int pos)
17 {
18 if (dep == m){
19 int cnt = 0;
20 pointsum = 0;
21 for (int i = 1; i <= n; i++)
22 if (use[i]){
23 cnt++;
24 pointsum += a[i];
25 }
26 if (cnt < m) return;
27 memset(d, 127, sizeof(d));
28 memset(vis, false, sizeof(vis));
29 int nx, mi = d[0] + 1;
30 edgesum = 0;
31 for (int j = 0; j <= m-1; j++){
32 mi = d[0] + 1;
33 for (int i = 1; i <= n; i++){
34 if (use[i] && !vis[i] && d[i] < mi){
35 nx = i;
36 mi = d[i];
37 }
38 }
39 vis[nx] = true;
40 if (d[nx] != d[0]) edgesum += d[nx];
41 for (int i = 1; i <= n; i++){
42 if (use[i] && d[i] > e[nx][i]){
43 d[i] = e[nx][i];
44 }
45 }
46 }
47 double tmp = double(edgesum)/double(pointsum);
48 if (tmp < bestratio){
49 bestratio = tmp;
50 int p = 1;
51 for (int i = 0; i < m; i++){
52 while(!use[p]) p++;
53 ans[i] = p;
54 p++;
55 }
56 }
57 else if (fabs(tmp - bestratio) < eps){
58 int p = 1;
59 for (int i = 0; i < m; i++){
60 while(!use[p]) p++;
61 tmpans[i] = p;
62 p++;
63 }
64 int i;
65 for (i = 0; i < m; i++){
66 if (tmpans[i] > ans[i]) return;
67 if (tmpans[i] < ans[i]) break;
68 }
69 if (i != m){
70 for (int j = 0; j < m; j++)
71 ans[j] = tmpans[j];
72 bestratio = tmp;
73 }
74 }
75 return;
76 }
77 for (int i = pos+1; i <= n; i++)
78 if (!use[i]){
79 use[i] = true;
80 dfs(dep+1, i);
81 use[i] = false;
82 }
83 }
84 int main()
85 {
86 while(scanf("%d %d", &n, &m) && n + m)
87 {
88 for (int i = 1; i <= n; i++)
89 scanf("%d", a+i);
90 int x, y, z;
91 for (int i = 1; i <= n; i++)
92 for (int j = 1; j <= n; j++){
93 scanf("%d", &z);
94 e[i][j] = z;
95 }
96 bestratio = 1e10;
97 memset(use, false, sizeof(use));
98 dfs(0, 0);
99 for (int i = 0; i < m-1; i++)
100 printf("%d ", ans[i]);
101 printf("%d\n", ans[m-1]);
102 }
103 return 0;
104 }
POJ 3926 Parade
按行转移,很容易就可以推出转移方程,然后需要单调队列优化复杂度,目前还没写。
POJ 3927 Priest John‘s Busiest Day
贪心的思路还是很明确的,因为牧师祝福的时间要超过长度的一半,所以中间的位置是必须要经过的,我们就按这个来排序,从头开始,尽量把祝福时间往前放,留给后面更多空间,如果这样还不能保证中间位置不重叠,那就是NO了。
但是具体的边界细节我想得不是很清楚,本来想乘以2就可以规避左右一奇一偶的情况,但是后来又想不清楚了。。反正也AC了。。不想管了。。
1 #include<cstdio>
2 #include<cstring>
3 #include<cmath>
4 #include<algorithm>
5 using namespace std;
6
7 struct node{
8 long long l, r;
9 } a[100100];
10 bool cmp(node a, node b)
11 {
12 return a.r + a.l <= b.r + b.l;
13 }
14 int n;
15 int main()
16 {
17 while(scanf("%d", &n) && n)
18 {
19 for (int i = 0; i < n; i++){
20 scanf("%lld%lld", &a[i].l, &a[i].r);
21 a[i].l *= 2ll;
22 a[i].r *= 2ll;
23 }
24 sort(a, a + n, cmp);
25 bool flag = true;
26 long long pre = 0;
27 for (int i = 0; i < n; i++){
28 long long tmp = (a[i].l + a[i].r)/2ll;
29 if (pre >= tmp){
30 flag = false;
31 break;
32 }
33 pre = 1ll + max(pre, a[i].l) + (a[i].r - a[i].l)/2ll;
34 }
35 if (flag)
36 puts("YES");
37 else
38 puts("NO");
39 }
40 return 0;
41 }
POJ 3928 Ping pong
主要就是一个统计的过程,需要一个查找比较快的数据结构,树状数组就可以胜任。
1 #include<cstdio>
2 #include<cstring>
3 using namespace std;
4
5 const int maxn = 100000;
6 int T;
7 int bef[20010], aft[20010], a[20010], equ[20010][2];
8 int pre[maxn+100], nex[maxn+100];
9 long long ans;
10 int n;
11 int lowbit(int x)
12 {
13 return x & -x;
14 }
15 void update(int x, int val, int sum[])
16 {
17 for (int i = x; i <= maxn; i += lowbit(i))
18 sum[i] += val;
19 }
20 int query(int x, int sum[])
21 {
22 int ans = 0;
23 for (int i = x; i > 0; i -= lowbit(i))
24 ans += sum[i];
25 return ans;
26 }
27 int main()
28 {
29 scanf("%d", &T);
30 while(T--)
31 {
32 memset(pre, 0, sizeof(pre));
33 memset(nex, 0, sizeof(nex));
34 scanf("%d", &n);
35 for (int i = 1; i <= n; i++){
36 scanf("%d", &a[i]);
37 bef[i] = query(a[i], pre);
38 equ[i][0] = bef[i] - query(a[i]-1, pre);
39 update(a[i], 1, pre);
40 }
41 for (int i = n; i >= 1; i--){
42 aft[i] = query(a[i], nex);
43 equ[i][1] = aft[i] - query(a[i]-1, nex);
44 update(a[i], 1, nex);
45 }
46 ans = 0;
47 for (int i = 1; i <= n; i++){
48 ans += (long long) bef[i] * (n-i-aft[i]) + (long long) (i-1-bef[i]) * aft[i];
49 ans += (long long) equ[i][0] * equ[i][1];
50 }
51 printf("%lld\n", ans);
52 }
53 return 0;
54 }
POJ 3929 Timer
virtual赛的时候还推了半天。。微积分水平还是比较拙计的。。现在还没做出来。。
POJ 3930 Elevator
很大一只模拟。。目测是不会去写了。。
08年acm区域赛北京赛区 部分题解题报告,布布扣,bubuko.com
原文:http://www.cnblogs.com/james47/p/3871890.html