• 编程之美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 }
  • 相关阅读:
    索引
    排序---冒泡排序、快速排序、选择排序、插入排序、希尔排序
    设计模式6大原则
    InputStream的read()读取机制
    Java中的关键字---native
    Java中的关键字---static
    Java中的关键字---transient
    负载均理解
    2020-03-29 微服务网关GateWay
    2020-03-28 微服务网关Zuul
  • 原文地址:https://www.cnblogs.com/sylvanas2012/p/3009194.html
Copyright © 2020-2023  润新知