hihocoder编程练习赛52

hihocoder编程练习赛52

A

描述

一般我们在对字符串排序时,都会按照字典序排序。当字符串只包含小写字母时,相当于按字母表”abcdefghijklmnopqrstuvwxyz”的顺序排序。
现在我们打乱字母表的顺序,得到一个26个字母的新顺序。例如”bdceafghijklmnopqrstuvwxyz”代表’b’排在’d’前,’d’在’c’前,’c’在’e’前……
给定N个字符串,请你按照新的字母顺序对它们排序。

输入
第一行包含一个整数N。(1 <= N <= 1000)
第二行包含26个字母,代表新的顺序。
以下N行每行一个字符串S。 (|S| <= 100)

输出
按新的顺序输出N个字符串,每个字符串一行。

样例输入
5
bdceafghijklmnopqrstuvwxyz
abcde
adc
cda
cad
ddc

样例输出
ddc
cda
cad
abcde
adc

参考AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<bits/stdc++.h>
#define maxn 1050
using namespace std;
int n;
string s1,s2[maxn];
map<char,char>mp1,mp2;
int main(){
// freopen("input.txt","r",stdin);
cin>>n;
cin>>s1;
mp1.clear(),mp2.clear();
for(int i=0;i<26;i++){
mp1[s1[i]]=i+'a';
mp2[i+'a']=s1[i];
}
for(int i=1;i<=n;i++){
cin>>s2[i];
int len=s2[i].length();
for(int j=0;j<len;j++) s2[i][j]=mp1[s2[i][j]];
}
sort(s2+1,s2+1+n);
for(int i=1;i<=n;i++){
int len=s2[i].length();
for(int j=0;j<len;j++) s2[i][j]=mp2[s2[i][j]];
cout<<s2[i]<<endl;
}
return 0;
}

思路

两个map双向映射
把原来的字母映射成abcd··· 然后用sring直接sort 再映射回去

B

C

描述
小Hi在Hihoole公司的实习期结束了。在回学校前,他决定请部门所有同事来住所聚会。
已知小Hi一共有N名同事,编号1~N,其中第i名同事的酒量是Ai。
这N名同事的上下级关系恰好组成一棵树型结构。对于第i名同事来说,如果他的直接上级没有出席聚会,他会喝掉Ai单位的酒;如果他的直接上级出席了聚会,他会有所收敛,只喝掉Ai/2单位的酒。
小Hi想知道,自己至少要准备多少单位的酒,才能保证无论哪些人出席聚会,酒都够喝。

输入
第一行包含一个整数N。(1 <= N <= 100000)
第二行包含N个整数,A1, A2, … AN。(0 <= Ai <= 100000)
以下N-1行每行包含两个整数u和v,代表u是v的直接上级。

输出
小Hi至少需要准备的酒量,保留1位小数。

样例输入
5
5 2 4 1 4
2 4
2 1
1 5
1 3

样例输出
10.5

参考AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<bits/stdc++.h>
#define maxn 100050
using namespace std;
vector<int>e[maxn];
int n,root;
int a[maxn],in[maxn],out[maxn];
double dp[maxn][2];
void dfs(int x){
if(out[x]==0){
dp[x][0]=0.0;
dp[x][1]=(double)a[x];
return;
}
double sum1=0.0,sum2=0.0;
for(int i=0;i<e[x].size();i++){
int nextx=e[x][i];
dfs(nextx);
sum1+=max(dp[nextx][0],dp[nextx][1]); //根不参加
sum2+=max(dp[nextx][0],dp[nextx][1]-a[nextx]/2.0); //根参加
}
dp[x][0]=sum1;
dp[x][1]=(double)a[x]+sum2;
}
int main(){
// freopen("input.txt","r",stdin);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
memset(in,0,sizeof in);
memset(out,0,sizeof out);
memset(dp,0,sizeof dp);
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
e[x].push_back(y);
in[y]++,out[x]++;
}
root=0;
for(int i=1;i<=n;i++){
if(in[i]==0){
root=i;
break;
}
}
dfs(root);
printf("%.1lf\n",max(dp[root][0],dp[root][1]));
return 0;
}

思路

树形dp
dp[x][0]表示x号结点不参加获得的最大价值
dp[x][1]表示x号结点参加获得的最大价值
无根树换有根树
转移方程:
dp[x][0]=子树max(dp[next][0],dp[next][1])求和
dp[x][1]=子树max(dp[nextx][0],dp[nextx][1]-a[nextx]/2.0) 根参加 所有子树参加的价值要减去自身的一半

文章目录
  1. 1. hihocoder编程练习赛52
    1. 1.1. A
      1. 1.1.1. 参考AC代码
      2. 1.1.2. 思路
    2. 1.2. B
    3. 1.3. C
      1. 1.3.1. 参考AC代码
      2. 1.3.2. 思路
|