天梯赛练习(一)

L2-017. 人以群分

题意:

给定n个正整数,  然后分成规模相差尽可能接近的两类, 这两类之和相差要尽可能大

分析:

直接排序, 然后分成两部分即可

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int a[123456];
 4 int sum(int l , int r){
 5     int ans = 0;
 6     for(int i = l; i <= r; i++) ans += a[i];
 7     return ans;
 8 }
 9 int main()
10 {
11     int n;
12     scanf("%d", &n);
13     for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
14     sort(a + 1, a + n + 1);
15     int mid = n / 2;
16     printf("Outgoing #: %d
Introverted #: %d
Diff = %d
",n-mid, mid, sum(mid+1, n) - sum(1,mid));
17     return 0;
18 }
人以群分

L2-019. 悄悄关注

题意:

给定一个关注列表, 然后再给出一个对每个用户的点赞数, 如果有一个对某一个用户的点赞数大于平均值而且该用户不在关注列表中, 输出。

分析:

用一个set保存关注列表, 用一个map去储存用户点赞数, 最后遍历一次map即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 set<string> focus; //关注列表
 4 map<string, int > like; //点赞数
 5 int main()
 6 {
 7     int n, m;
 8     cin >> n;
 9     string temp;
10     for(int i = 0; i < n; i++){
11         cin >> temp;
12         focus.insert(temp);
13     }
14     double sum = 0;
15     int a;
16     cin >> m;
17     for(int i = 0; i < m; i++){
18         cin >> temp >> a;
19         like[temp] += a;
20         sum += a;
21     }
22     sum /= (double)m;
23     int flag = 0;
24     for(auto it = like.begin(); it != like.end(); it++){
25         if(it->second > sum && !focus.count(it->first)) {
26                 flag = 1;
27                 cout << it->first << "
";
28         }
29     }
30     if(!flag) cout << "Bing Mei You
";
31 }
悄悄关注

L2-020. 功夫传人

题意:

给定一个师傅徒弟家谱,每个师傅可以收很多个徒弟, 每个徒弟只能有一个师傅, 然后一开始有一个祖师爷有功力值Z。每代传递会有一个损耗r,徒弟有可能出现“得道者”会将功力放大k倍,但是“得道者”不会收徒弟,  求出“得道者”功力之和。

分析:

家谱成一个树形结构, 用BFS遍历一遍, 每次遇到“得道者”将功力加上即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e5 + 7;
 4 int n;
 5 double z, r;
 6 double quickpow(double a,int b)//快速幂
 7 {
 8     double ans = 1;
 9     while(b)//用一个循环从右到左便利b的所有二进制位
10     {
11         if(b&1)//判断此时b[i]的二进制位是否为1
12         {
13             ans = (ans*a);//乘到结果上,这里a是a^(2^i)%m
14             b--;//把该为变0
15         }
16         b/=2;
17         a = a*a;
18     }
19     return ans;
20 }
21 struct node{
22     int n, dynasty; //编号、 传递了几代
23     node(int _n, int _dynasty):n(_n), dynasty(_dynasty){}
24 };
25 int F[maxn], master[maxn];
26 vector<int> apprentice[maxn];
27 int main()
28 {
29     scanf("%d %lf %lf", &n, &z, &r);
30     r = (100 - r)/100;
31     for(int i = 0; i < n; i++){
32         int num;
33         scanf("%d", &num);
34         if(num == 0){
35             int t;
36             scanf("%d", &t);
37             master[i] = t;
38         }
39         else{
40             for(int j = 0; j < num; j++){
41                 int t;
42                 scanf("%d", &t);
43                 apprentice[i].push_back(t);
44             }
45         }
46     }
47     double ans = 0;
48     queue<node> q;
49     q.push(node(0,0));
50     while(!q.empty()){
51         node u = q.front(); q.pop();
52         int name = u.n , d = u.dynasty
53         if(master[name])
54         {
55             ans += quickpow(r,d) * z * (double)master[name];
56         }
57         else
58         for(int i = 0; i < apprentice[name].size(); i++){
59             q.push(node(apprentice[name][i], d + 1));
60         }
61     }
62     printf("%d
", (int)ans);
63     return 0;
64 }
功夫传人

L3-013. 非常弹的球

题意:

给出一个球的质量, 求在一个平面抛出能得到的最远距离。

分析:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const double eps = 1e-6;
 4 int main()
 5 {
 6     double w, p, E, v, ans;
 7     scanf("%lf%lf", &w, &p);
 8     E = 1000, ans = 0;
 9     w /= 100;
10     do{
11         v = sqrt(2*E/w);
12         ans += v*v/9.8;
13         E *= ((100-p)/100);
14     }while(v > eps);
15     printf("%.3f", ans);
16 }
非常弹的球

L3-015. 球队“食物链”

题意:

给定N支队伍的2*N场双循环赛结果, 求出一条包含所有球队的“食物链”,“食物链”为一个1至N的排列{ T1 T2 ... TN },满足:球队T1战胜过球队T2,球队T2战胜过球队T3,……,球队T(N-1)战胜过球队TN,球队TN战胜过球队T1。若存在多条“食物链”,请找出字典序最小的。

分析:

因为这条食物链如果存在, 那么一定是包含所有球队的, 所以可以从第一个点开始DFS,有一个剪枝是“如果还没选择的点没有与1相连接的, 剪枝”。

另外要注意的是图并不是对称的, a输b==b赢a。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 bool g[25][25];
 4 bool vis[25];
 5 int pick[25];
 6 int n, ok;
 7 bool dfs(int index , int tot)
 8 {
 9     if(tot == n){
10         if(g[index][0] == 1){
11             printf("%d", pick[0] + 1);
12             for(int i = 1; i < n; i++) printf(" %d", pick[i] + 1); puts("");
13             return true;
14         }
15         return false;
16     }
17     int cut = 1;//剪枝, 如果剩下没挑选的点都没有与1相连的,剪枝。
18     for(int i = 0; i < n; i++){
19         if(!vis[i] && g[i][0] == 1) {
20             cut = 0;
21             break;
22         }
23     }
24     if(cut) return false;
25     for(int i = 0; i < n; i++){
26         if(g[index][i] == 1 && !vis[i]){
27             vis[i] = 1;
28             pick[tot] = i;
29             if(dfs(i, tot + 1)) return true;
30             vis[i] = 0;
31         }
32     }
33     return false;
34 }
35 int main()
36 {
37     scanf("%d ", &n);
38     char input[123];
39     for(int i = 0; i < n; i++){
40         gets(input);
41         for(int j = 0; j < n; j++)
42             if( input[j] == 'W') g[i][j] = 1;
43             else if( input[j] == 'L') g[j][i] = 1;//注意a输b其实等于b赢a
44     }
45     vis[0] = 1;
46     pick[0] = 0;
47     ok = dfs(0, 1);
48     if(!ok) printf("No Solution
");
49 }
球队“食物链”
原文地址:https://www.cnblogs.com/Jadon97/p/8094399.html