涵盖知识点:贪心、思维、图论
比赛链接:
https://codeforces.com/contest/1321
A:Contest for Robots
题意:有n道题。事先知道两个机器人(R,B)分别能答对哪几道。现在要分配每题得分使得机器人R一定能赢(至少1分),问怎么分配使得所有题的最高分最低。
题解:贪心。分别计算R对B错和R错B对的数量,然后把R错B对的题全部设置为1分。所以R对B错的题尽可能平均分且超过R错B对的题数即可。
Accept Code:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=110; 4 int r[maxn],b[maxn]; 5 int main(){ 6 int n,cnt1=0,cnt2=0; 7 cin>>n; 8 for(int i=0;i<n;i++){ 9 cin>>r[i]; 10 } 11 for(int i=0;i<n;i++){ 12 cin>>b[i]; 13 if(r[i]>b[i])cnt1++; 14 if(r[i]<b[i])cnt2++; 15 } 16 if(cnt1==0)cout<<"-1 "; 17 else cout<<cnt2/cnt1+1<<" "; 18 return 0; 19 }
B:Journey Planning
题意:n个地点编号1~n。每个地点有一个美丽指数bi。现在要制定一个浏览顺序使得浏览过的城市的美丽指数之和最大。要求如下
(1)浏览顺序必须为严格递增序列
(2)相邻浏览的城市必须满足编号的差等于美丽指数的差
题解:将bi转移为bi-i即可,map记录总和,最后扫描一遍取最大值。
Accept Code:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 map<int,ll> mp; 5 int main(){ 6 int n; 7 cin>>n; 8 for(int i=1;i<=n;i++){ 9 int b; 10 cin>>b; 11 mp[b-i]+=b; 12 } 13 ll ans=0; 14 for(auto i:mp){ 15 ans=max(ans,i.second); 16 } 17 cout<<ans<<" "; 18 return 0; 19 }
C:Remove Adjacent
题意:给定一个小写字母字符串。具体操作规则如下:若一个字母的相邻字母为它字典序中的前一个字母,则可以将这个字母删除。问最多能操作几次。
题解:注意到字符串长度仅100.所以暴力解决。顺序从z扫描到a。每次删除一个字母后记得重新扫描一遍即可。理论上最坏复杂度100*100*26
Accept Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main(){ 4 int n; 5 string w; 6 cin >> n >> w; 7 bool flag = true; 8 while (flag) { 9 flag = false; 10 for (char i = 'z';i > 'a';--i) { 11 for (int j = 0;j < w.size();++j){ 12 if (w[j] == i) { 13 if ((j > 0 && w[j-1] == i-1) || (j+1 < w.size() && w[j+1] == i-1)) { 14 w.erase(w.begin() + j); 15 flag = true; 16 break; 17 } 18 } 19 } 20 if (flag) break; 21 } 22 } 23 cout << n - w.size() << ' '; 24 25 26 }
D:Navigation System
题意:给定一个单向图和一个规划完的s~t路径。有一个导航仪会实时显示当前点到t的最短路径(但并不会已经规划完的路径产生影响)。如果规划的路径和导航路径不同,那么走到下一个点后,导航仪会重新规划路径。问导航仪最少和最多重新规划几次。
题解:设p为规划路径。dis[p[i]]为p[i]~t的最短距离。导航仪在如下几种情况下会重新规划:
(1)dis[p[i]]-1≠dis[p[i+1]]。即一定不是最短路径。
(2)存在一个不为p[i+1]的点w使得dis[p[i]]-1=dis[w]。即存在一条其他的路径为最短路径。
不难发现如果第一种情况发生,那么第二种情况一定存在。所以满足第一条即为最少的规划次数,满足第二条的即为最多的规划次数。
对于dis数组的获得逆向bfs一下即可。
Accept Code:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=2e5+10,inf=0x3f3f3f3f; 4 int n,m,k; 5 vector<int> edg[maxn],gde[maxn]; 6 int p[maxn],dis[maxn]; 7 void bfs(int s){ 8 queue<int> q; 9 memset(dis,inf,sizeof dis); 10 q.push(s); 11 dis[s]=0; 12 while(!q.empty()){ 13 int t=q.front(); 14 q.pop(); 15 for(auto i:gde[t]){ 16 if(dis[i]==inf){ 17 dis[i]=dis[t]+1; 18 q.push(i); 19 } 20 } 21 } 22 } 23 int main(){ 24 cin>>n>>m; 25 for(int i=1;i<=m;i++){ 26 int x,y; 27 cin>>x>>y; 28 edg[x].push_back(y); 29 gde[y].push_back(x); 30 } 31 cin>>k; 32 for(int i=1;i<=k;i++) 33 cin>>p[i]; 34 bfs(p[k]); 35 int res1=0,res2=0; 36 for(int i=1;i<k;i++){ 37 int u=p[i],v=p[i+1]; 38 if(dis[u]!=dis[v]+1) 39 res1++; 40 for(auto w:edg[u]){ 41 if(v!=w&&dis[w]+1==dis[u]) { 42 res2++; 43 break; 44 } 45 } 46 } 47 cout<<res1<<" "<<res2<<" "; 48 return 0; 49 }