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

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM