2011年珠海赛 H题 Rolling

  1 /*
  2 题意:给出一个球体,桌面是红色染料,球在上面滚会染上一些线,给出滚的方向和距离,求球面上染的线将球面分成的几个块中最大块的面积
  3 
  4 题解:模拟+建图+连通
  5 因为球的半径为2/PI,因此滚动一圈恰好是4,给出的是整数的距离,说明每次滚动都是N个1/4圆的长度,然后将整个球面分成8块,每块给一个位置标记0~7,每转动1的距离,就相当于将相邻的两块分割开,就变成了求8块连通的区域在通过转动切割边之后剩下的最大的连通分量数目,因此在每次的转动模拟四个方向(转动即相当于切割),至于模拟的方法就是用0~7固定标记在球的表面,每次的转动这些标记也会跟随转动,然后把8个标记模拟放置到下一个数组当中,然后建成一个8*8的图,每个块为一个点,两个相邻的块加一条边,每一次染1/4色相当于删除一条边,可以重复删边,最后模拟完后就可以直接通过图求点数最多的连通分量的点得数目,然后乘上面积即可
  6 */
  7 #include <cstdio>
  8 #include <cstring>
  9 #include <cmath>
 10 
 11 const double PI = acos(-1.0);
 12 
 13 int ball[8]; // 球转动前各个面的位置状态
 14 int dir[4][8]={
 15     {4,5,1,0,7,6,2,3},
 16     {3,2,6,7,0,1,5,4},
 17     {4,0,3,7,5,1,2,6},
 18     {1,5,6,2,0,4,7,3}
 19 };//从上到下方向为N,S,W,E,d[][j]表示j位置的块移动到d[][j]位置
 20 
 21 bool vis[10];
 22 
 23 int dfs(int u, int map[][8])
 24 {
 25     int ret = 0;
 26     for(int i=0; i<8; i++)
 27     {
 28         if (u != i && !vis[i] && map[u][i])
 29         {
 30             vis[i] =true;
 31             ret += dfs(i,map);
 32         }
 33     }
 34     return ret + 1;
 35 }
 36 
 37 int main(void)
 38 {
 39     int t,d;
 40     char s[10];
 41     scanf("%d",&t);
 42     while (t--)
 43     {
 44         int n;
 45         scanf("%d",&n);
 46         // 先建好没有去除任何边前的图
 47         int map[8][8] =
 48         {{0,1,0,1,1,0,0,0},
 49         {1,0,1,0,0,1,0,0},
 50         {0,1,0,1,0,0,1,0},
 51         {1,0,1,0,0,0,0,1},
 52         {1,0,0,0,0,1,0,1},
 53         {0,1,0,0,1,0,1,0},
 54         {0,0,1,0,0,1,0,1},
 55         {0,0,0,1,1,0,1,0}};
 56         for(int i=0; i<8; i++)
 57             ball[i] = i;
 58         while (n--)
 59         {
 60             scanf("%s%d",s,&d);
 61             if (d >= 4)
 62                 d = 4 + d % 4; // 此处小坑,不能直接MOD 4,当值为4,MOD了之后就等于没有任何线加上,因此要注意
 63             if (strcmp(s,"NORTH") == 0)
 64             {
 65                 for(int i=0; i<d; i++)
 66                 {
 67                     map[ball[4]][ball[5]] = map[ball[5]][ball[4]] = 0; // 画了一条线就要删除该边
 68                     int tmp[8];
 69                     for(int j=0; j<8; j++)
 70                     {
 71                         tmp[j] = ball[j];
 72                     }
 73                     for(int j=0; j<8; j++)
 74                     {
 75                         ball[dir[0][j]] = tmp[j]; // 球旋转,每一块转到对应位置
 76                     }
 77                 }
 78             }
 79             else if (strcmp(s,"SOUTH") == 0)
 80             {
 81                 for(int i=0; i<d; i++)
 82                 {
 83                     map[ball[6]][ball[7]] = map[ball[7]][ball[6]] = 0;
 84                     int tmp[8];
 85                     for(int j=0; j<8; j++)
 86                     {
 87                         tmp[j] = ball[j];
 88                     }
 89                     for(int j=0; j<8; j++)
 90                     {
 91                         ball[dir[1][j]] = tmp[j];
 92                     }
 93                 }
 94             }
 95             else if (strcmp(s,"WEST") == 0)
 96             {
 97                 for(int i=0; i<d; i++)
 98                 {
 99                     map[ball[4]][ball[7]] = map[ball[7]][ball[4]] = 0;
100                     int tmp[8];
101                     for(int j=0; j<8; j++)
102                     {
103                         tmp[j] = ball[j];
104                     }
105                     for(int j=0; j<8; j++)
106                     {
107                         ball[dir[2][j]] = tmp[j];
108                     }
109                 }
110             }
111             else
112             {
113                 for(int i=0; i<d; i++)
114                 {
115                     map[ball[6]][ball[5]] = map[ball[5]][ball[6]] = 0;
116                     int tmp[8];
117                     for(int j=0; j<8; j++)
118                     {
119                         tmp[j] = ball[j];
120                     }
121                     for(int j=0; j<8; j++)
122                     {
123                         ball[dir[3][j]] = tmp[j];
124                     }
125                 }
126             }
127         }
128         int ans = -1;
129         memset(vis,false,sizeof(vis));
130         for(int i=0; i<8; i++)
131         {
132             if (!vis[i])
133             {
134                 vis[i] = true;
135                 int t = dfs(i,map);
136                 if (ans < t)
137                     ans = t;
138             }
139         }
140 
141         printf("%.3lf\n",ans*2.0/PI);
142     }
143     return 0;
144 }                                 

 

 

 
 
 
1007. Problem H Rolling
 
     
     
     
 
Time Limit: 1sec    Memory Limit:256MB
Description

 It is an interesting problem. Imagine there is a ball on a boundless ground. Initially the ball is white and the ground is red. Now, the ball starts to roll on the ground, and is dyed with red by the ground. A point on the surface of the ball will turn to red when it touches the ground. Finally the ball stops and the surface of the ball may be divided into several parts. You should calculate the area of the largest part. The radius of the ball is 2 / PI (PI is circumference ratio).

Input
The first line of the input is an integer T, the number of test cases (0 < T <= 10).
Then T test case followed. In each test case, the first line contains an integer N (0 <= N <= 10000), the number of rolling operation of the ball. Each of the next N line contains a string S and an integer D, separated by spaces. S will be one of {‘EAST’, ‘WEST’, ‘NORTH’, ‘SOUTH’}, means the direction of the ball rolling operation, and D means the distance of the ball rolling operation. The ball will roll on the ground with the given N operation by the order of input.
Output

 For each test case, output one real, rounded to 3 decimal places, the area of the largest part of surface of the ball.

Sample Input
3
1
EAST 1000000
3
NORTH 1
WEST 1
SOUTH 1
2
WEST 1
EAST 1
Sample Output
2.546
4.456
5.093

Problem Source: test_one

 
   
posted @ 2014-03-31 00:16  辛力啤  阅读(265)  评论(0编辑  收藏  举报