Ural Regional School Programming Contest 2011
链接:Ural Regional School Programming Contest 2011
【2014/05/25】今天的训练做了一套大水题,最后的rank是7道题,如下,第8题在比赛结束的一分钟中居然AC了,真是神奇啊,可惜时间过了。
【题意】一篇参赛记录的文章,让你统计每个队员参赛的次数。
【思路】水题,同时也很坑爹,主要是统计很麻烦,文章很长同时是英文,读都要读大半天,WA了,后来检查了一下AC了。
1 #include <cstdio> 2 3 int a[] = {5,20,12,2,1,4,6,1,4,4,1,0}; 4 int main() 5 { 6 int n; 7 scanf("%d",&n); 8 printf("%d\n",a[n]); 9 return 0; 10 }
【题意】有一面墙,给你长度为a和b的两个木棒,通过墙,地面和木棒,围成一个四边形,使其面积最大。
【思路】直接枚举边AB,然后AB确定之后,三角形ABD面积就确定了,用海伦公式去运算。至于三角形ABO,由于其是个直角三角形,AB边长度确定之后,AO,BO可以变化,再加上勾股定理,求其面积的时候利用消元得到一个关于AB的一元二次方程,其最值是AO=BO的时候得到的,所以三角形AOB的面积最大值是 (K*K)/4. 于是最后的四边形面积是一个关于K的三角形ABD的面积用海伦公式知道是关于K的一元二次方程,具体很难化简到一般形式,所以用三分来枚举,因为他是个凸型函数。K是变长,范围是[0,a+b].
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 #define EPS 1e-10 6 using namespace std; 7 8 double a, b; 9 10 double GetS(double k) 11 { 12 double p = (a + b + k) / 2; 13 return k*k/4 + sqrt(p*(p-a)*(p-b)*(p-k)); 14 } 15 int main() 16 { 17 scanf("%lf%lf", &a, &b); 18 double l = 0 , r = a + b; 19 while(l + EPS < r) 20 { 21 double m1 = l + (r - l)/3; 22 double m2 = r - (r - l)/3; 23 if(GetS(m1) >= GetS(m2)) 24 r = m2; 25 else 26 l = m1; 27 } 28 printf("%.9f\n", GetS(l)); 29 return 0; 30 }
【题意】说是有一只蜈蚣,左边40条腿,右边40条腿,它有a只左鞋,b只右鞋,然后有一个穿鞋的方法,说它今天特别倒霉,求最多要多长时间穿好鞋,算是一个推公式的题吧。
【思路】考虑最坏情况,第一种最坏情况,很明显,就是把右脚的鞋子全穿一遍,然后再穿完左脚,耗时2b+40。第二种情况,先穿完左脚,再穿完右脚?不不不,还有更糟糕的情况,先给右脚穿好39只,耗时39*2,然后给左脚穿完鞋子,耗时40,再把剩下的左脚鞋子都上一遍,耗时2*(a-40),然后穿上右脚最后一只,耗时1。总耗时39+2a。取其最大值即可。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 int main() 6 { 7 int a, b; 8 scanf("%d%d",&a,&b); 9 printf("%d\n",max(b*2+40,2*a+39)); 10 return 0; 11 }
【题意】某地有2个锁,有个小偷每天都去开锁(递增,从0000开始,每天一次),这个地方每天换个锁(第一天1号锁,第二天2号,第三天还是1号,第四天2号......),如果小偷能在9999之前开锁(开一次就可以了)。输出yes,否则no.
【思路】大水题,直接判断1号锁是否是偶数,或者2号锁是否是奇数,即小偷能够解锁。
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 int main() 6 { 7 char str[5]; 8 int x, y; 9 10 scanf("%s", str); 11 sscanf(str, "%d", &x); 12 scanf("%s", str); 13 sscanf(str, "%d", &y); 14 15 if(x%2==1 && y%2==0) 16 puts("no"); 17 else 18 puts("yes"); 19 20 return 0; 21 }
【题意】有一个特殊的4阶魔方,只能横着转。每一层只有4个格子有颜色(4种颜色,有颜色格子旋转对称,每一层有颜色格子位置不同),所以从上面看刚好是一个4*4的彩色方块。(结合原图图像理解题意)给定一个初始状态,要求到指定状态的最小步数。
【思路】这就是那个时间到了之后才AC的题,用string来存储状态,BFS过了。
1 #include <cstdio> 2 #include <map> 3 #include <queue> 4 #include <string> 5 using namespace std; 6 7 struct state 8 { 9 int arr[4][4]; 10 string tostring() 11 { 12 string res = ""; 13 for (int i = 0; i < 4; i++) 14 { 15 for (int j = 0; j < 4; j++) 16 { 17 res = res + (char)(arr[i][j]+'0'); 18 } 19 } 20 return res; 21 } 22 }; 23 24 state tostate(string x) 25 { 26 state t; 27 for (int i = 0; i < 4; i++) 28 { 29 for (int j = 0; j < 4; j++) 30 { 31 t.arr[i][j] = x[i*4+j]-'0'; 32 } 33 } 34 return t; 35 } 36 map<string, int> hs; 37 38 bool check(state x) 39 { 40 int v = x.arr[0][0]; 41 for (int i = 0; i < 2; i++) 42 { 43 for (int j = 0; j < 2; j++) 44 { 45 if (x.arr[i][j]!=v) return false; 46 } 47 } 48 v = x.arr[0][2]; 49 for (int i = 0; i < 2; i++) 50 { 51 for (int j = 2; j < 4; j++) 52 { 53 if (x.arr[i][j]!=v) return false; 54 } 55 } 56 v = x.arr[2][0]; 57 for (int i = 2; i < 4; i++) 58 { 59 for (int j = 0; j < 2; j++) 60 { 61 if (x.arr[i][j]!=v) return false; 62 } 63 } 64 v = x.arr[2][2]; 65 for (int i = 2; i < 4; i++) 66 { 67 for (int j = 2; j < 4; j++) 68 { 69 if (x.arr[i][j]!=v) return false; 70 } 71 } 72 return true; 73 } 74 75 76 void bfs(state s) 77 { 78 queue<state> q; 79 q.push(s); 80 hs[s.tostring()] = 0; 81 while(!q.empty()) 82 { 83 state e = q.front(); 84 q.pop(); 85 if (check(e)) 86 { 87 printf("%d\n",hs[e.tostring()]); 88 return; 89 } 90 state t; 91 for (int i = 1; i <= 8; i++) 92 { 93 t = e; 94 if (i == 1) 95 { 96 t.arr[0][0] = e.arr[0][3]; 97 t.arr[0][3] = e.arr[3][3]; 98 t.arr[3][3] = e.arr[3][0]; 99 t.arr[3][0] = e.arr[0][0]; 100 } 101 if (i == 2) 102 { 103 t.arr[0][0] = e.arr[3][0]; 104 t.arr[3][0] = e.arr[3][3]; 105 t.arr[3][3] = e.arr[0][3]; 106 t.arr[0][3] = e.arr[0][0]; 107 } 108 if (i == 3) 109 { 110 t.arr[1][1] = e.arr[1][2]; 111 t.arr[1][2] = e.arr[2][2]; 112 t.arr[2][2] = e.arr[2][1]; 113 t.arr[2][1] = e.arr[1][1]; 114 } 115 if (i == 4) 116 { 117 t.arr[1][1] = e.arr[2][1]; 118 t.arr[1][2] = e.arr[1][1]; 119 t.arr[2][2] = e.arr[1][2]; 120 t.arr[2][1] = e.arr[2][2]; 121 } 122 if (i == 5) 123 { 124 t.arr[1][0] = e.arr[0][2]; 125 t.arr[0][2] = e.arr[2][3]; 126 t.arr[2][3] = e.arr[3][1]; 127 t.arr[3][1] = e.arr[1][0]; 128 } 129 if (i==6) 130 { 131 t.arr[1][0] = e.arr[3][1]; 132 t.arr[3][1] = e.arr[2][3]; 133 t.arr[2][3] = e.arr[0][2]; 134 t.arr[0][2] = e.arr[1][0]; 135 } 136 if (i==7) 137 { 138 t.arr[0][1] = e.arr[1][3]; 139 t.arr[1][3] = e.arr[3][2]; 140 t.arr[3][2] = e.arr[2][0]; 141 t.arr[2][0] = e.arr[0][1]; 142 } 143 if (i==8) 144 { 145 t.arr[0][1] = e.arr[2][0]; 146 t.arr[2][0] = e.arr[3][2]; 147 t.arr[3][2] = e.arr[1][3]; 148 t.arr[1][3] = e.arr[0][1]; 149 } 150 if (hs.find(t.tostring())==hs.end()) 151 { 152 hs[t.tostring()] = (hs[e.tostring()] + 1); 153 q.push(t); 154 } 155 else if (hs[t.tostring()]>hs[e.tostring()]+1) 156 { 157 hs[t.tostring()] = hs[e.tostring()]+1; 158 q.push(t); 159 } 160 } 161 } 162 } 163 164 int main() 165 { 166 state st; 167 for (int i = 0; i < 4; i++) 168 { 169 for(int j = 0; j < 4; j++) 170 { 171 scanf("%d",&st.arr[i][j]); 172 } 173 } 174 bfs(st); 175 return 0; 176 }
【题意】一个ACM小队三个队员,每个人有n个数值,求出三个队员都相同的数值的个数。
【思路】水题,set搞定。
1 #include <cstdio> 2 #include <cstring> 3 #include <set> 4 #include <algorithm> 5 6 using namespace std; 7 8 set<int> b[3]; 9 10 int main() 11 { 12 #ifdef HotWhite 13 freopen("in.txt", "r", stdin); 14 #endif 15 int cnt[3], num, mini = 10000000; 16 for (int i = 0; i < 3; ++i) { 17 scanf("%d", cnt+i); 18 if (mini == 10000000 || cnt[i] < mini) { 19 mini = i; 20 } 21 for (int j = 0; j < cnt[i]; ++j) { 22 scanf("%d", &num); 23 b[i].insert(num); 24 } 25 } 26 set<int>::iterator ite = b[mini].begin(); 27 int res = 0; 28 for ( ; ite != b[mini].end(); ++ite) { 29 if (b[0].count(*ite) && b[1].count(*ite) && b[2].count(*ite)) { 30 res++; 31 } 32 } 33 printf("%d\n", res); 34 return 0; 35 }
【题意】页数统计,给出每一页可以打印多少行,每一行最多多少个字符,然后给出一串单词,让求需要打印多少张
【思路】直接模拟即可,水题。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 int h, w, n; 8 int cnt; 9 10 struct Word { 11 char str[110]; 12 int len; 13 } word[10007]; 14 15 int main() 16 { 17 #ifdef HotWhite 18 freopen("in.txt", "r", stdin); 19 #endif 20 scanf("%d %d %d", &h, &w, &n); 21 for (int i = 0; i < n; ++i) { 22 scanf("%s", word[i].str); 23 word[i].len = strlen(word[i].str); 24 } 25 int tem, j = 0, tot = 0; 26 while (j < n) { 27 tem = w - word[j++].len; 28 while (j < n && 1+word[j].len <= tem) { 29 tem -= 1+word[j].len; 30 j++; 31 } 32 tot++; 33 } 34 printf("%d", (tot+(h-1))/h); 35 return 0; 36 }
【题意】一个方形的生日蛋糕,上面有n个蜡烛,要求从上面切下来一块,包含k个蜡烛,输出其中一个解即可。
【思路】计算几何题目,凸包的巧妙应用。
1 #include <cstdio> 2 #include <cmath> 3 #include <algorithm> 4 #define INF 1e9 5 #define EPS 1e-8 6 using namespace std; 7 8 int dcmp(double x) 9 { 10 if (fabs(x)<EPS) return 0; 11 return x < 0?-1:1; 12 } 13 14 struct Point 15 { 16 double x,y; 17 Point(double x = 0, double y = 0):x(x),y(y) {} 18 bool operator < (const Point a) const 19 { 20 if (dcmp(x-a.x)==0) return dcmp(y-a.y)<0?1:0; 21 else return dcmp(x-a.x)<0?1:0; 22 } 23 } pt[10005],cpt[10005],cov[10005]; 24 typedef Point Vector; 25 26 27 Vector operator - (Point A , Point B) 28 { 29 return Vector(A.x-B.x,A.y-B.y); 30 } 31 double Cross(Vector A, Vector B) 32 { 33 return A.x*B.y-A.y*B.x; 34 } 35 36 double lenth(Vector v) 37 { 38 return sqrt(v.x*v.x+v.y*v.y); 39 } 40 41 bool cmp(Point a, Point b) 42 { 43 Vector v2 = b - pt[0]; 44 Vector v1 = a - pt[0]; 45 if (dcmp(Cross(v1,v2))==0) 46 { 47 return dcmp(lenth(v1)-lenth(v2))<=0?true:false; 48 } 49 else 50 { 51 return dcmp(Cross(v1,v2))<0?true:false; 52 } 53 } 54 55 int Convexhull(Point * p, int n, Point * ch) 56 { 57 sort(p,p+n); 58 int m = 0; 59 for (int i = 0; i < n; i++) 60 { 61 while(m>1 && dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])) <= 0) m--; 62 ch[m++]=p[i]; 63 } 64 int k = m; 65 for (int i = n-2; i >=0; i--) 66 { 67 while(m>k && dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])) <=0) m--; 68 ch[m++]=p[i]; 69 } 70 if (n>1)m--; 71 return m; 72 } 73 74 75 int main() 76 { 77 int n, k; 78 scanf("%d%d",&n,&k); 79 for (int i = 0; i <n; i++) 80 { 81 double x,y; 82 scanf("%lf%lf",&x,&y); 83 pt[i] = Point(x,y); 84 if (dcmp(pt[i].x-pt[0].x)==-1) 85 { 86 swap(pt[0],pt[i]); 87 } 88 else if (dcmp(pt[i].x-pt[0].x)==0&&dcmp(pt[i].y-pt[0].y)<=0) 89 { 90 swap(pt[0],pt[i]); 91 } 92 } 93 sort(pt+1,pt+n,cmp); 94 int cnt = 0; 95 cpt[cnt++] = pt[0]; 96 for (int i = 1; i < n; i++) 97 { 98 cpt[cnt++] = pt[i]; 99 if (cnt == k) break; 100 } 101 if (k <= 2) 102 { 103 printf("%d\n",3); 104 if (k == 1) 105 { 106 printf("-1000000000 -1000000000\n"); 107 printf("%.0f %.0f\n",cpt[0].x, cpt[0].y); 108 printf("-1000000000 1000000000\n"); 109 } 110 if (k == 2) 111 { 112 printf("%.0f %.0f\n",cpt[0].x,cpt[0].y); 113 printf("%.0f %.0f\n",cpt[1].x,cpt[1].y); 114 printf("-1000000000 1000000000\n"); 115 } 116 } 117 else 118 { 119 int m = Convexhull(cpt,cnt,cov); 120 if (m == 2) 121 { 122 printf("%d\n",3); 123 printf("%.0f %.0f\n",cov[0].x,cov[0].y); 124 printf("%.0f %.0f\n",cov[1].x,cov[1].y); 125 printf("-1000000000 1000000000\n"); 126 } 127 else 128 { 129 printf("%d\n", m); 130 for (int i = 0; i < m; i++) 131 { 132 printf("%.0f %.0f\n",cov[i].x,cov[i].y); 133 } 134 } 135 } 136 return 0; 137 }