编程之美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 }

 

 

 

 

 

你可能感兴趣的:(编程之美)