码迷,mamicode.com
首页 > 其他好文 > 详细

08年acm区域赛北京赛区 部分题解题报告

时间:2014-07-27 23:14:39      阅读:351      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   os   数据   io   

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

就是个小模拟。开始忘记了一个小框完全覆盖大框的情况。然后还有一种容易忽略的情况是,被遮住只剩下一行。我是判断能不能从一个点出发再走回到自己,然后遍历左上到右下,没有其他框的代表字母即可。

bubuko.com,布布扣
 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 }
View Code

 

POJ 3924  Tornado

貌似是最难的一道,计算几何,还没做。

 

POJ 3925  Minimal Ratio Tree

乍一看很厉害,其实点数很少,直接枚举所选的点,然后就是求最小生成树了。开始读错题,以为答案是升序排列,字典序最大的,多了很多无用代码和一个WA。。然后读入没读好,后面懒得改就写了手很生的prim。。代码挺挫。。

bubuko.com,布布扣
  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 }
View Code

 

 

POJ 3926  Parade

按行转移,很容易就可以推出转移方程,然后需要单调队列优化复杂度,目前还没写。

 

POJ 3927  Priest John‘s Busiest Day

贪心的思路还是很明确的,因为牧师祝福的时间要超过长度的一半,所以中间的位置是必须要经过的,我们就按这个来排序,从头开始,尽量把祝福时间往前放,留给后面更多空间,如果这样还不能保证中间位置不重叠,那就是NO了。

但是具体的边界细节我想得不是很清楚,本来想乘以2就可以规避左右一奇一偶的情况,但是后来又想不清楚了。。反正也AC了。。不想管了。。

bubuko.com,布布扣
 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 }
View Code

 

 

POJ 3928  Ping pong

主要就是一个统计的过程,需要一个查找比较快的数据结构,树状数组就可以胜任。

bubuko.com,布布扣
 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 }
View Code

 

POJ 3929  Timer

virtual赛的时候还推了半天。。微积分水平还是比较拙计的。。现在还没做出来。。

 

POJ 3930  Elevator

很大一只模拟。。目测是不会去写了。。

08年acm区域赛北京赛区 部分题解题报告,布布扣,bubuko.com

08年acm区域赛北京赛区 部分题解题报告

标签:des   style   blog   http   color   os   数据   io   

原文地址:http://www.cnblogs.com/james47/p/3871890.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!