编程之美2013资格赛 水结

 很久没有在线编程了,实力大大减弱。为了保持算法与编程的技能,继续找一下在线比赛来复习复习。只为找感觉,不求排名与晋级。

一 传话游戏

http://programming2013.cstnet.cn/qualification/problem/1

题目简意:一句由若干个单词组成的话,经过N个人传承。每个人在听取前一个人的口述时,都会把某些单词听成另外的单词。求最终被流传下来的句子。

解: 不能再水了,就是简单的字符串替换。不想用c写字符串的东西,于是用了java的HashMap<String,String>,还是第一次用java提交。注意类名一定要是Main

View Code
 1  
 2 import java.util.HashMap;
 3 import java.util.Scanner;
 4 
 5 public class Main{
 6     
 7     
 8 public static int T, N, M;
 9 
10 public static int count = 1;
11 public static HashMap<String,String> rule;
12 
13 public static String   orignal, result;
14 public static Scanner cin = new Scanner(System.in);
15 
16 
17     public static void main(String[] args){
18         
19         T = cin.nextInt();
20         
21         while(T-- > 0)
22         {
23             N = cin.nextInt();
24             M = cin.nextInt();
25             result = "";
26              
27             rule = new HashMap<String,String>();
28             for(int i = 0; i < M; i++)
29             {
30                 String ori = cin.next().toString();
31                 String swp = cin.next().toString();
32                 rule.put(ori, swp);
33             }
34             
35             orignal = cin.next().toString();
36             orignal += cin.nextLine().toString();
37              
38             
39             String[] sentence = orignal.split(" ");
40             
41             
42             while(N > 1)
43             {
44                 for(int i = 0; i < sentence.length; i++)
45                     if (rule.containsKey(sentence[i]))
46                         sentence[i] = rule.get(sentence[i]);                     
47                 N--;
48             }
49             
50             String result = "";
51             for (int i=0;i<sentence.length;i++)
52                 result += " "+sentence[i];
53             
54             System.out.println("Case #" + count++ + ":" + result);
55             
56         }
57     } 
58 
59 }

二 长方形

http://programming2013.cstnet.cn/qualification/problem/2

题目概要:在 N 条水平线与 M 条竖直线构成的网格中,放 K 枚石子,每个石子都只能放在网格的交叉点上。问在最优的摆放方式下,最多能找到多少四边平行于坐标轴的长方形,它的四个角上都恰好放着一枚石子。 

输入:第一行,给出一个整数T,为数据组数。接下来依次给出每组测试数据。

每组数据为三个用空格隔开的整数 N,M,K。

1 ≤ T ≤ 100

0 ≤ K ≤ N * M

小数据:0 < N, M ≤ 30

大数据:0 < N, M ≤ 30000

解:这是一道排列组合的问题。假设我们已经知道从K个石子中取X*Y个组成一个大的饱满的矩形,它上面每一行的石子数目相同,剩余L个石子,0<L<X。则此时的矩形总数为:在饱满的大矩形中,共有C(x,2)*C(y,2)个小矩形,剩下的和L有关的矩形数是X*C(L,2) 。两者的和即为所求。

如何选取X和Y呢?应该可以理论证明的,但是我懒得去推,因为N,M<= 30000, 可以枚举每一个X的值。(似乎真的太懒了。。。)

View Code
 1 #include<stdio.h>
 2 #include<math.h>
 3 
 4 unsigned long long solve()
 5 {
 6     int i,j,k;
 7     int t,n,m;
 8     unsigned long long mx = 0;
 9     int x,y,l;
10     unsigned long long cur;
11     
12     scanf("%d%d%d",&n,&m,&k);
13     if (n>m)
14     {
15         t=n;n=m;m=t;
16     }
17     for (i=2;i<=n;i++)
18     {
19         x=i; 
20         y = k / i;
21         l = k % i;
22         if (y>m || y==m && l>0)
23           continue;
24         cur = x*y*(x-1)*(y-1)/4 + y * (l-1)*l/2;
25         if (cur>mx)
26           mx = cur;        
27     }
28     return mx;    
29 }
30 
31 int main()
32 {
33     int T,i;
34     scanf("%d",&T);
35     for (i=1;i<=T;i++)
36         printf("Case #%d: %llu\n",i,solve());
37     return 0;
38 }

这个平台和杭电的又有所不同,输出不能用%I64d ,而要用%llu 来输出 unsigned long long。

三 树上的三角形

有一棵树,树上有只毛毛虫。它在这棵树上生活了很久,对它的构造了如指掌。所以它在树上从来都是走最短路,不会绕路。它还还特别喜欢三角形,所以当它在树上爬来爬去的时候总会在想,如果把刚才爬过的那几根树枝/树干锯下来,能不能从中选三根出来拼成一个三角形呢?

1 ≤ T ≤ 5

小数据:1 ≤ N ≤ 100, 1 ≤ M ≤ 100, 1 ≤ len ≤ 10000

大数据:1 ≤ N ≤ 100000, 1 ≤ M ≤ 100000, 1 ≤ len ≤ 1000000000

解:一看就让人想到用最近公共祖先和并查集。但是我现在不想花太多精力去实现它,于是就决定水一下小数据。

首先要说的是,小数据的范围是1000,而不是100!害我检查了N次,太无耻了。

拿到树的结构以后,任取一个节点,遍历一遍树,为了得到每个节点的深度(假设根节点的深度为0)和它的父节点。

然后对每一对节点s和t,沿着他们的父节点一层一层上移,直到遇到第一个公共祖先。(利用每个节点的深度)。并把这条路径上的边压入一个数组中。

接着对保存有边的数组进行排序。遍历一次排序好的数组,如果存在相邻的三条边能构成三角形,那么就yes,否则就no。

View Code
  1 #include<stdio.h>
  2 #define size 900
  3 int N,M;
  4 int c[size][size];
  5 int dep[size];
  6 int father[size];
  7 int visited[size];
  8 int edge[size];
  9 int cnt;
 10 
 11 void Broadcast(int s, int d  )
 12 {
 13     int i;
 14     
 15     visited[s] = 1;
 16     dep[s] = d;
 17     int fa,fb;
 18     
 19        
 20     for (i=1;i<=N;i++)
 21        if (visited[i]==0 && c[s][i]>0)
 22        {
 23           father[i] = s;
 24           Broadcast(i,d+1 );
 25        }
 26 }
 27  
 28 void sort(int s[] , int cnt)
 29 {
 30     int t;
 31     int i,j;
 32     for (i=0;i<cnt;i++)
 33       for (j=i+1;j<=cnt;j++)
 34         if (s[i]>s[j])
 35         {
 36           t = s[i];
 37           s[i] = s[j];
 38           s[j] = t;
 39         }
 40 }
 41 
 42 void solve()
 43 {
 44 
 45     int i,j,k;
 46     int s,t,w;
 47     int ok ;
 48     int fa,fb;
 49     scanf("%d",&N);
 50     
 51     
 52     for (i=1;i<=N;i++)
 53     {
 54       visited[i] = 0;
 55       for (j=1;j<=N;j++)
 56       {
 57          c[i][j] = 0;
 58          c[j][i] = 0;
 59          }
 60     }
 61     
 62     for (i=1;i<N;i++)
 63        {
 64           scanf("%d %d %d",&s,&t,&w);
 65           c[s][t] = w;
 66           c[t][s] = w;
 67        }
 68        
 69     scanf("%d",&M);
 70     father[1] = 1;
 71     
 72     Broadcast(1,0 );
 73     for (k=0;k<M;k++)
 74     {
 75         scanf("%d %d",&s,&t);
 76     //    printf("No\n");
 77     //    continue;
 78         fa = s;
 79         fb = t;
 80         cnt = 0;
 81      
 82         while (fa != fb)
 83         {
 84             if (dep[fa]>dep[fb])
 85             {
 86                 fa = father[fa];
 87             }
 88             else fb = father[fb];
 89         }
 90         
 91         while (s != fa)
 92         {
 93             edge[cnt++] = c[s][father[s]];
 94             s = father[s];
 95         }
 96         while (t != fa)
 97         {
 98             edge[cnt++] = c[t][father[t]];
 99             t = father[t];
100         }
101      
102          //qsort(edge,0,cnt-1);
103         sort(edge,cnt-1);
104         ok = 0;
105         for (i=0;i<cnt-2;i++)
106         {
107             if (edge[i]+edge[i+1] > edge[i+2])
108             {
109               ok = 1;
110               break;
111             }
112         }
113         if (ok==1)
114           printf("Yes\n");
115           else printf("No\n");
116     }
117 }
118 
119 int main()
120 {
121     int T;
122     int i;
123     scanf("%d",&T);
124     for (i=1;i<=T;i++)
125     {
126         printf("Case #%d:\n",i);
127         solve();           
128     }
129     return 0;
130 }
原文地址:https://www.cnblogs.com/sylvanas2012/p/3009194.html