ZOJ Monthly, August 2014

135 - ZOJ Monthly, August 2014

A:构造问题,判断序列奇偶性,很容易发现最小值不是1就是0,最大值不是n就是n - 1,注意细节去构造即可

E:dp,dp[i][j]表示长度i,末尾状态为j的最大值,然后每个位置数字取与不取,不断状态转移即可

G:就一个模拟题没什么好说的

H:dfs,每次dfs下去,把子树宽度保存下来,然后找最大值,如果有多个,就是最大值+cnt宽度

I:构造,如果r * 2 > R,肯定无法构造,剩下的就二分底边,按等腰三角形去构造即可

代码:

A:

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <cmath>  
  4. #include <algorithm>  
  5. using namespace std;  
  6.   
  7. int n;  
  8.   
  9. void print(int n) {  
  10.     if (n == 3) {  
  11.     printf("3 1 2");  
  12.     return;  
  13.     }  
  14.     if (n % 2) {  
  15.     int len = (n - 3) / 2;  
  16.     printf("%d %d", n, n - len);  
  17.     for (int i = n - 1; i > n - len; i--)  
  18.         printf(" %d %d", i, i - len);  
  19.     printf(" 3 1 2");  
  20.     }  
  21.     else {  
  22.     int len = n / 2;  
  23.     printf("%d %d", n, n - len);  
  24.     for (int i = n - 1; i > n - len; i--)  
  25.         printf(" %d %d", i, i - len);  
  26.     }  
  27. }  
  28.   
  29. void print2(int n) {  
  30.     print(n - 2);  
  31.     printf(" %d %d", n - 1, n);  
  32. }  
  33.   
  34. void solve() {  
  35.     if (n == 1) {  
  36.     printf("1 1\n1\n1\n");  
  37.     return;  
  38.     }  
  39.     if (n == 2) {  
  40.     printf("1 1\n1 2\n2 1\n");  
  41.     return;  
  42.     }  
  43.     if (n == 3) {  
  44.     printf("0 2\n3 1 2\n1 2 3\n");  
  45.     return;  
  46.     }  
  47.     if (n % 2 == 0) {  
  48.     if (n / 2 % 2) {  
  49.         printf("1 %d\n", n - 1);  
  50.         print2(n); printf("\n");  
  51.         print2(n - 1);  
  52.         printf(" %d\n", n);  
  53.     }  
  54.     else {  
  55.         printf("0 %d\n", n);  
  56.         print(n); printf("\n");  
  57.         print(n - 1); printf(" %d\n", n);  
  58.     }  
  59.     }  
  60.     else {  
  61.     if ((n + 1) / 2 % 2) {  
  62.         printf("1 %d\n", n);  
  63.         print(n - 2); printf(" %d %d\n", n - 1, n);  
  64.         print(n - 1); printf(" %d\n", n);  
  65.     }  
  66.     else {  
  67.         printf("0 %d\n", n - 1);  
  68.         print(n); printf("\n");  
  69.         print2(n - 1); printf(" %d\n", n);  
  70.     }  
  71.     }  
  72. }  
  73.   
  74. int main() {  
  75.     while (~scanf("%d", &n)) {  
  76.     solve();  
  77.     }  
  78.     return 0;  
  79. }  

E:

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <algorithm>  
  4. #include <map>  
  5. using namespace std;  
  6.   
  7. const int INF = 0x3f3f3f3f;  
  8. int t, n;  
  9.   
  10. map<intint> dp[2];  
  11. map<intint>::iterator it;  
  12.   
  13. int lowbit(int x) {  
  14.     return (x&(-x));  
  15. }  
  16.   
  17. int solve() {  
  18.     dp[0].clear();  
  19.     int pre = 1, now = 0;  
  20.     int num;  
  21.     dp[0][0] = 0;  
  22.     for (int i = 0; i < n; i++) {  
  23.     scanf("%d", &num);  
  24.     num /= 2;  
  25.     swap(pre, now);  
  26.     dp[now].clear();  
  27.     for (it = dp[pre].begin(); it != dp[pre].end(); it++) {  
  28.         int s = it->first;  
  29.         if (dp[now].count(s) == 0) dp[now][s] = dp[pre][s];  
  30.         else dp[now][s] = max(dp[now][s], dp[pre][s]);  
  31.         int next;  
  32.         if (s % num) {  
  33.         next = num;  
  34.         if (dp[now].count(next) == 0) dp[now][next] = dp[pre][s] + num * 2;  
  35.         else dp[now][next] = max(dp[now][next], dp[pre][s] + num * 2);  
  36.         }  
  37.         else {  
  38.         next = s + num;  
  39.         int add = (s % lowbit(next) * 2 + num) * 2;  
  40.         if (dp[now].count(next) == 0) dp[now][next] = dp[pre][s] + add;  
  41.         else dp[now][next] = max(dp[now][next], dp[pre][s] + add);  
  42.         }  
  43.     }  
  44.     }  
  45.     int ans = 0;  
  46.     for (it = dp[now].begin(); it != dp[now].end(); it++)  
  47.     ans = max(ans, it->second);  
  48.     return ans;  
  49. }  
  50.   
  51. int main() {  
  52.     scanf("%d", &t);  
  53.     while (t--) {  
  54.     scanf("%d", &n);  
  55.     printf("%d\n", solve());  
  56.     }  
  57.     return 0;  
  58. }  

G:

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <vector>  
  4. #include <algorithm>  
  5. using namespace std;  
  6.   
  7. const int N = 55;  
  8. const int d[8][2] = {{1, 0}, {1, 1}, {1, -1}, {0, 1}, {0, -1}, {-1, 0}, {-1, 1}, {-1, -1}};  
  9.   
  10. typedef pair<intint> pii;  
  11.   
  12. int t;  
  13. int n, m, f, k;  
  14. int g[N][N];  
  15. int gg[N][N];  
  16. char str[55];  
  17. vector<pii> go[1005];  
  18.   
  19. void solve() {  
  20.     for (int ti = 1; ti <= f; ti++) {  
  21.     memset(gg, 0, sizeof(gg));  
  22.     for (int i = 1; i <= n; i++) {  
  23.         for (int j = 1; j <= m; j++) {  
  24.         if (g[i][j] == 1) {  
  25.             for (int k = 0; k < 8; k++) {  
  26.             int xx = i + d[k][0];  
  27.             int yy = j + d[k][1];  
  28.             if (xx <= 0 || xx > n || yy <= 0 || yy > m) continue;  
  29.             gg[xx][yy]++;  
  30.             }  
  31.         }  
  32.         }  
  33.     }  
  34.   
  35.     for (int i = 1; i <= n; i++)  
  36.         for (int j = 1; j <= m; j++) {  
  37.         if (g[i][j] == 2) continue;  
  38.         else if (g[i][j] == 0) {  
  39.             if (gg[i][j] == 3) g[i][j] = 1;  
  40.         }  
  41.         else {  
  42.             if (gg[i][j] < 2 || gg[i][j] > 3) g[i][j] = 0;  
  43.         }  
  44.         }  
  45.     for (int i = 0; i < go[ti].size(); i++) {  
  46.         g[go[ti][i].first][go[ti][i].second] = 2;  
  47.     }  
  48.     }  
  49.     for (int i = 1; i <= n; i++) {  
  50.     for (int j = 1; j <= m; j++) {  
  51.         if (g[i][j] == 2) printf("X");  
  52.         else printf("%d", g[i][j]);  
  53.     }  
  54.     printf("\n");  
  55.     }  
  56. }  
  57.   
  58. int main() {  
  59.     scanf("%d", &t);  
  60.     while (t--) {  
  61.     scanf("%d%d%d%d", &n, &m, &f, &k);  
  62.     for (int i = 1; i <= f; i++)  
  63.         go[i].clear();  
  64.     for (int i = 1; i <= n; i++) {  
  65.         scanf("%s", str + 1);  
  66.         for (int j = 1; j <= m; j++) {  
  67.         g[i][j] = str[j] - '0';  
  68.         }  
  69.     }  
  70.     int ti, x, y;  
  71.     while (k--) {  
  72.         scanf("%d%d%d", &ti, &x, &y);  
  73.         go[ti].push_back(make_pair(x, y));  
  74.     }  
  75.     solve();  
  76.     }  
  77.     return 0;  
  78. }  

H:

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <vector>  
  4. #include <algorithm>  
  5. using namespace std;  
  6.   
  7. const int N = 10005;  
  8.   
  9. int n;  
  10. vector<int> g[N];  
  11.   
  12. int dfs(int u) {  
  13.     int sz = g[u].size();  
  14.     vector<int> save;  
  15.     for (int i = 0; i < sz; i++)  
  16.     save.push_back(dfs(g[u][i]));  
  17.     sort(save.begin(), save.end());  
  18.     sz = save.size();  
  19.     int cnt = 0;  
  20.     int ans = 1;  
  21.     for (int i = sz - 1; i >= 0; i--) {  
  22.     if (i != sz - 1 && save[i] != save[i + 1]) break;  
  23.     ans = save[i] + cnt;  
  24.     cnt++;  
  25.     }  
  26.     return ans;  
  27. }  
  28.   
  29. int main() {  
  30.     while (~scanf("%d", &n)) {  
  31.     for (int i = 1; i <= n; i++)  
  32.         g[i].clear();  
  33.     int v;  
  34.     for (int i = 2; i <= n; i++) {  
  35.         scanf("%d", &v);  
  36.         g[v].push_back(i);  
  37.     }  
  38.     printf("%d\n", dfs(1));  
  39.     }  
  40.     return 0;  
  41. }  

I:

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <cmath>  
  4.   
  5. double r, R;  
  6.   
  7. double h, x;  
  8.   
  9. double cal(double a) {  
  10.     double d = a / 2;  
  11.     h = sqrt(R * R - d * d) + R;  
  12.     x = sqrt(h * h + d * d);  
  13.     return a * x * x / (2 * R * (a + x + x));  
  14. }  
  15.   
  16. void solve() {  
  17.     double lx = 0, rx = sqrt(3.0) * R;  
  18.     double mid;  
  19.     for (int i = 0; i < 1000; i++) {  
  20.     mid = (lx + rx) / 2;  
  21.     double tmp = cal(mid);  
  22.     if (tmp > r) rx = mid;  
  23.     else lx = mid;  
  24.     }  
  25.     cal((lx + rx) / 2);  
  26.     printf("%.10lf %.10lf %.10lf\n", mid, x, x);  
  27. }  
  28.   
  29. int main() {  
  30.     while (~scanf("%lf%lf", &r, &R)) {  
  31.     if (r * 2 > R) printf("NO Solution!\n");  
  32.     else solve();  
  33.     }  
  34.     return 0;  
  35. }  





A Abs Problem http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5330

找规律题,构造出解。copyright@ts

复制代码
 1 #include<cstdio>
 2 int main() {
 3     int n,big,sma,id;
 4     while(~scanf("%d",&n)) {
 5         if(n==1) {
 6             puts("1 1");
 7             puts("1");
 8             puts("1");
 9             continue;
10         }
11         if(n==2) {
12             puts("1 1");
13             puts("1 2");
14             puts("2 1");
15             continue;
16         }
17         if(!((n-3)%4)||!(n%4)) {
18             sma=0;
19         }
20         else {
21             sma=1;
22         }
23         if(sma) {
24             if(n&1) {
25                 big=n;
26                 id=3;
27             }
28             else {
29                 big=n-1;
30                 id=4;
31             }
32         }
33         else {
34             if(n&1) {
35                 big=n-1;
36                 id=1;
37             }
38             else {
39                 big=n;
40                 id=2;
41             }
42         }
43         printf("%d %d\n",sma,big);
44         printf("%d",n);
45         for(int i=n-1;i>=1;i--) {
46             printf(" %d",i);
47         }
48         puts("");
49         if(id==1||id==4) {
50             for(int i=n-3;i>=1;i--) {
51                 printf("%d ",i);
52             }
53             printf("%d %d %d\n",n-2,n-1,n);
54         }
55         else {
56             for(int i=n-1; i>=1; i--) {
57                 printf("%d ",i);
58             }
59             printf("%d\n",n);
60         }
61     }
62     return 0;
63 }
复制代码

 

 

G YY's Minions http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5336

模拟题,怎么说怎么做。

复制代码
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int M=64;
 5 char op[M];
 6 int mat[2][M][M],n,m,f,k,t;
 7 struct G{
 8     int t,x,y;
 9     friend bool operator <(G a,G b){
10         return a.t<b.t;
11     }
12 }g[M*M];
13 int dx[]={-1,-1,-1,0,0,1,1,1};
14 int dy[]={-1,0,1,-1,1,-1,0,1};
15 int sum(int x,int y,int pre){
16     int res=0;
17     for(int i=0,tx,ty;i<8;i++){
18         tx=x+dx[i];
19         ty=y+dy[i];
20         if(tx>=1&&tx<=n&&ty>=1&&ty<=m){
21             if(mat[pre][tx][ty]&1){
22                 res++;
23             }
24         }
25     }
26     return res;
27 }
28 int change(int pre,int num){
29     if(pre==0){
30         if(num==3) return 1;
31         return 0;
32     }
33     if(num==2||num==3) return 1;
34     return 0;
35 }
36 char tochar(int x){
37     if(x==2) return 'X';
38     return x+'0';
39 }
40 int main(){
41     while(~scanf("%d",&t)){
42         while(t--){
43             scanf("%d%d%d%d",&n,&m,&f,&k);
44             int pre=0,now=1;
45             for(int i=1;i<=n;i++){
46                 scanf("%s",op);
47                 for(int j=0;j<m;j++){
48                     mat[pre][i][j+1]=op[j]-'0';
49                 }
50             }
51             for(int i=0;i<k;i++){
52                 scanf("%d%d%d",&g[i].t,&g[i].x,&g[i].y);
53             }
54             sort(g,g+k);
55             for(int u=1,head=0;u<=f;u++,pre^=1,now^=1){
56                 for(int i=1;i<=n;i++){
57                     for(int j=1;j<=m;j++){
58                         if(mat[pre][i][j]==2){
59                             mat[now][i][j]=2;
60                             continue;
61                         }
62                         int num=sum(i,j,pre);
63                         mat[now][i][j]=change(mat[pre][i][j],num);
64                     }
65                 }
66                 while(head<k&&g[head].t==u){
67                     mat[now][g[head].x][g[head].y]=2;
68                     head++;
69                 }
70             }
71             for(int i=1;i<=n;i++){
72                 for(int j=1;j<=m;j++){
73                     putchar(tochar(mat[pre][i][j]));
74                 }
75                 putchar('\n');
76             }
77         }
78     }
79     return 0;
80 }
复制代码

 

 用vector就不用排序了。

复制代码
 1 #include<cstdio>
 2 #include<vector>
 3 using namespace std;
 4 const int M=64;
 5 char op[M];
 6 int mat[2][M][M],n,m,f,k,t;
 7 struct G{
 8     int x,y;
 9 }p;
10 vector<G> g[M*M];
11 int dx[]={-1,-1,-1,0,0,1,1,1};
12 int dy[]={-1,0,1,-1,1,-1,0,1};
13 int sum(int x,int y,int pre){
14     int res=0;
15     for(int i=0,tx,ty;i<8;i++){
16         tx=x+dx[i];
17         ty=y+dy[i];
18         if(tx>=1&&tx<=n&&ty>=1&&ty<=m){
19             if(mat[pre][tx][ty]&1){
20                 res++;
21             }
22         }
23     }
24     return res;
25 }
26 int change(int pre,int num){
27     if(pre==0){
28         if(num==3) return 1;
29         return 0;
30     }
31     if(num==2||num==3) return 1;
32     return 0;
33 }
34 char tochar(int x){
35     if(x==2) return 'X';
36     return x+'0';
37 }
38 int main(){
39     while(~scanf("%d",&t)){
40         while(t--){
41             scanf("%d%d%d%d",&n,&m,&f,&k);
42             int pre=0,now=1;
43             for(int i=1;i<=n;i++){
44                 scanf("%s",op);
45                 for(int j=0;j<m;j++){
46                     mat[pre][i][j+1]=op[j]-'0';
47                 }
48             }
49             for(int i=1;i<=f;i++){
50                 g[i].clear();
51             }
52             for(int i=0,ti;i<k;i++){
53                 scanf("%d%d%d",&ti,&p.x,&p.y);
54                 g[ti].push_back(p);
55             }
56             for(int u=1,head=0;u<=f;u++,pre^=1,now^=1){
57                 for(int i=1;i<=n;i++){
58                     for(int j=1;j<=m;j++){
59                         if(mat[pre][i][j]==2){
60                             mat[now][i][j]=2;
61                             continue;
62                         }
63                         int num=sum(i,j,pre);
64                         mat[now][i][j]=change(mat[pre][i][j],num);
65                     }
66                 }
67                 int lg=g[u].size();
68                 for(int i=0;i<lg;i++){
69                     mat[now][g[u][i].x][g[u][i].y]=2;
70                 }
71             }
72             for(int i=1;i<=n;i++){
73                 for(int j=1;j<=m;j++){
74                     putchar(tochar(mat[pre][i][j]));
75                 }
76                 putchar('\n');
77             }
78         }
79     }
80     return 0;
81 }
复制代码

 

 

 

H Machine http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5337

树的深搜。邻接表快一些

复制代码
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 #include<algorithm>
 5 #define mt(a,b) memset(a,b,sizeof(a))
 6 using namespace std;
 7 const int M=10010;
 8 struct G{
 9     struct E{
10         int v,next;
11     }e[M<<1];
12     int le,head[M];
13     void init(){
14         le=0;
15         mt(head,-1);
16     }
17     void add(int u,int v){
18         e[le].v=v;
19         e[le].next=head[u];
20         head[u]=le++;
21     }
22 }g;
23 vector<int> son[M];
24 int dfs(int u,int fa){
25     son[u].clear();
26     for(int i=g.head[u];~i;i=g.e[i].next){
27         int v=g.e[i].v;
28         if(v!=fa){
29             son[u].push_back(dfs(v,u));
30         }
31     }
32     sort(son[u].begin(),son[u].end());
33     int res=1,ls=son[u].size();
34     for(int i=0;i<ls;i++){
35         res=max(res,son[u][i]+ls-i-1);
36     }
37     return res;
38 }
39 int main(){
40     int n;
41     while(~scanf("%d",&n)){
42         g.init();
43         for(int v=2,u;v<=n;v++){
44             scanf("%d",&u);
45             g.add(u,v);
46             g.add(v,u);
47         }
48         printf("%d\n",dfs(1,-1));
49     }
50     return 0;
51 }
复制代码

 vector慢一些

复制代码
 1 #include<cstdio>
 2 #include<vector>
 3 #include<algorithm>
 4 using namespace std;
 5 const int M=10010;
 6 vector<int> g[M],son[M];
 7 int dfs(int u,int fa){
 8     son[u].clear();
 9     int lu=g[u].size();
10     for(int i=0;i<lu;i++){
11         int v=g[u][i];
12         if(v!=fa){
13             son[u].push_back(dfs(v,u));
14         }
15     }
16     sort(son[u].begin(),son[u].end());
17     int res=1,ls=son[u].size();
18     for(int i=0;i<ls;i++){
19         res=max(res,son[u][i]+ls-i-1);
20     }
21     return res;
22 }
23 int main(){
24     int n;
25     while(~scanf("%d",&n)){
26         for(int i=1;i<=n;i++){
27             g[i].clear();
28         }
29         for(int v=2,u;v<=n;v++){
30             scanf("%d",&u);
31             g[u].push_back(v);
32             g[v].push_back(u);
33         }
34         printf("%d\n",dfs(1,-1));
35     }
36     return 0;
37 }
复制代码

 

 

I Incircle and Circumcircle http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5338

机智的用不对的三分过了。定义圆都在y轴,定义三角形一个点在圆心,定义三角形是等腰的。

复制代码
 1 #include<cstdio>
 2 #include<cmath>
 3 const double eps=1e-10;
 4 double r,R;
 5 double f(double y) {
 6     double Y=2*R*(1-(r*r)/(y*y));
 7     return fabs(Y-y-r);
 8 }
 9 double TernarySearch(double L,double R) { // 三分查找
10     while(R-L>eps) {
11         double LL=(L*2+R)/3;
12         double RR=(L+R*2)/3;
13         if(f(LL)<f(RR))  //f为对应的值  这里求最小值
14             R=RR;
15         else
16             L=LL;
17     }
18     return L;
19 }
20 int main(){
21     int t1,t2;
22     while(~scanf("%d%d",&t1,&t2)){
23         if(t1*2>t2){
24             puts("NO Solution!");
25             continue;
26         }
27         r=t1;
28         R=t2;
29         double ansy=TernarySearch(r,R+R-r);
30         ansy+=r;
31         double tmp=ansy-r;
32         double sinxita=r/tmp;
33         double cosxita=sqrt(tmp*tmp-r*r)/tmp;
34         double a=ansy*tmp/sqrt(tmp*tmp-r*r);
35         double b=a;
36         double c=2*a*r/tmp;
37         printf("%.18f %.18f %.18f\n",a,b,c);
38     }
39     return 0;
40 }
复制代码

 

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值