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

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

时间: 2024-12-29 11:56:34

08年acm区域赛北京赛区 部分题解题报告的相关文章

[hdu5136]Yue Fei&#39;s Battle 2014 亚洲区域赛广州赛区J题(dp)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 现场赛的时候由于有个地方有点小问题,没有成功AC,导致与金牌失之交臂. 由于今天下午有点事情,无法打重现,所以下午只是花了十分钟做了一道J题,抢了个FB,2333333333 Yue Fei's Battle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)T

ACM总结——2017ACM-ICPC北京赛区现场赛总结

现在距离比赛结束已经过了一个多星期了,也是终于有时间写下心得了.回来就是被压着做项目,也是够够的. 这次比赛一样是我和两个学弟(虽然是学弟,但我的实力才是最弱的T_T)一起参加的,成绩的话打铁,算是情理之中意料之外了,我们本来以为自己会在北京赛区拿个倒数20什么的(比赛前听说北京赛区是最难的),事实上虽然不是很简单,但是也绝对没有想象中难(以为会A1或者零来着). 说下比赛前吧~赛前一星期是软考,所有自己训练很少,也正是这样,这场比赛算是抱了大腿(自己太菜了..)!咳咳~虽然软考复习了两周,但是

2015亚洲区域赛长春赛区网络预选赛

第一次打网络赛,第一场,总体来说还可以吧,但是我们队三个人状态都并不太好,主要就是 WA 的比较多吧,开场看最后一题是我的习惯了,虽然貌似那题到打了一半可能才有队伍做出来了,我看了感觉像前几天训练赛的时候做的一道题.刻盘开场看 06 ,凯神开场 01.接着两分钟学长发现 07 水题我就跟着看了发题意,求区间最大值,静态.然后数据范围也很小,就直接开敲暴力,四分钟的时候过的,大概 20 名左右吧,那就是我们的最高名次了2333……接着我准备继续研究下 13 ,刻盘告诉我 06 是关于循环的子串的问

第39届ACM亚洲区域赛牡丹江赛区赛后总结

2014年10月10日,周五,早晨匆匆忙忙的出了寝室,直奔复印社去打了两份模板,然后直接就去上课了.第三节课下课,直接跟老师讲了一声,就去实验室跟学长们汇合了.12点半,踏上了开往牡丹江的列车,我们那节车厢俨然成了参赛队伍的专列了,背后坐的是吉大的,学生还没咋看,主要都看他们教练了,那肚子挺得,那得多腐败啊...旁边的是华南理工的,没想到旁边的那个妹纸,竟然是他们的教练!!!看着就是学生呀,竟然已经留校当教练了,唉,好可惜(你们懂得,嘿嘿~~~) 抵达牡丹江,这是我第二次踏上这块土地,当时想着这

ZOJ3822 ACM-ICPC 2014 亚洲区域赛牡丹江赛区现场赛D题Domination 概率DP(两种解法)

题目地址:点击打开链接 这道题有两种做法,第一种是直接求期望,类似于poj 2096 区别在于这个步数有限.所以要迭代步数. #include <cstdio> #include <cstring> #include <iostream> #define maxn 55//这里刚开始写成了50+10 那么maxn*maxn就会小很多wa了一次 using namespace std; double dp[maxn][maxn][maxn*maxn]; int N,M,T

2013区域赛长沙赛区现场赛 K - Pocket Cube

K - Pocket Cube Time Limit:10000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4801 Description Pocket Cube is a 3-D combination puzzle. It is a 2 × 2 × 2 cube, which means it is constructed by 8 mini-cubes.

树状数组 LA 4329 亚洲赛北京赛区题

复习下树状数组 还是蛮有意思的一道题: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=501&page=show_problem&problem=4174 学到几点: 1.树状数组C[i]的构建,一则c[i]=s[i]-s[i-lowbit(i)];这是一直用的做法.如今学到一种新的,直接add(i,a[i]),(s[i]为a[1]到a[i]的和) 2.前缀和思想,

2013 ACM区域赛长沙 H zoj 3733 (hdu 4798) Skycity

题意:一个圆台,底面和顶面半径分别为R,r,然后高度为H,一共F层,每层高度一样,然后要在每层的天花板上贴方格玻璃,方格玻璃要满足以下几个条件: 方格玻璃面积不能小于S,且方格玻璃要围成一个正多边形,且正好将天花板围住(也就是说天花板的圆面是这个多边形的内接圆),并且要使得贴的玻璃数量尽量少,也就是说这个正多边形的边数要尽量少.问最后所用玻璃的总面积. 思路:先求每个圆的半径,也就是等差数列.再二分正多边行数量.二分容易出错,此题还有精度要求..... 1 #include <iostream>

2017 ACM区域赛现场赛 青岛站 E (polya计数)

题目链接(暂无) 吐槽:这场比赛感觉对我感觉还算友好,虽然Q群知乎上命题方已经被喷死了,C语言上机题还有字符串题有大腿队友轻松搞定,网络流恰是我能想出来的,E本来也应该是在能力范围内,不过因为之前没写过跑程序搜置换的题,一时看到就发怵..万幸过掉了K题网络流拿到了金,不然场上没写E打铜得后悔死我.. 题意:一个3*3*1的长方体,有3*3(顶面)+3*4(侧面)+3*3(底面)=30个待染色的小面,长方体有四个可扭动的轴,位于四条边的中间那个1*1*1的小块,每次可扭动180°.支持的基本的置换