0
点赞
收藏
分享

微信扫一扫

Codeforces Round #715 (Div. 2) A~C题解


文章目录

  • ​​A. Average Height​​
  • ​​B. TMT Document​​
  • ​​C. The Sports Festival​​

A. Average Height

  • 解题思路
    水题,题目意思其实要求相邻数之和能凑出更多的偶数,那必然是奇数+奇数,偶数+偶数。将奇数和偶数分别存储起来输出即可。
  • AC代码
/**
*@filename:A_Average_Height
*@author: pursuit

*@created: 2021-04-16 22:36
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;

int t,n;
vector<int> odd,even;
void solve(){
for(int i=0;i<odd.size();i++){
cout<<odd[i]<<" ";
}
for(int i=0;i<even.size();i++){
cout<<even[i]<<" ";
}
cout<<endl;
}
int main(){
while(cin>>t){
while(t--){
cin>>n;
int temp;
odd.clear(),even.clear();
for(int i=0;i<n;i++){
cin>>temp;
if(temp%2)odd.push_back(temp);
else even.push_back(temp);
}
solve();
}
}
return 0;
}

B. TMT Document

解题思路
此题我采用模拟的方式去做这道题。我们来细细分析,按照模拟的方法,我们会去配对​​​TMT​​​。用一个哈希表来记录字符出现的次数,那么在遍历字符串的过程中,我们就可以开始配对,配对的标志其实就是围绕​​M​​​这个字符,倘若我们遇到了​​M​​​,那么我们需要做的就是寻找左右边的​​T​​,对于左边,我们毫无顾忌,找一个​​T​​和它配对即可,即是利用哈希表中的​​T​​数量来判断, 而对于右边,即是当我们碰到​​T​​​的时候,我们开始抉择了,如果此时的​​M​​​是大于Codeforces Round #715 (Div. 2) A~C题解_算法的,那么这个时候我们需要配对​​​M​​​,但是,并不意味着我们需要去用此时的​​T​​​来配对,因为这个​​T​​​很可能就是下一个​​M​​​左边的​​T​​​,而且右边的​​T​​​出现在哪都可以与当前的​​M​​​配对,所以我们假设它配对成功,并统计它所需要的​​T​​​,最后我们遍历完之后判断哈希表中未用的​​T​​​是否刚好是​​cnt​​,故此题得解。需要注意的是:我们总能证明最后剩下的​​T​​一定是在​​M​​的右边,不然我们不会累加,注意这段程序:

if(p['M']>0){
p['M']--;//已经被配对。
//这个T可以在任何位置,存储需要的t。
cnt++;
}

AC代码

/**
*@filename:B_TMT_Document
*@author: pursuit

*@created: 2021-04-16 22:46
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;

int t,n;
string s;
map<char,int> p;
void solve(){
p.clear();
bool flag=true;
int cnt=0;
for(int i=0;i<n;i++){
p[s[i]]++;
if(s[i]=='M'){
if(p['T']==0){
flag=false;
break;
}
else{
p['T']--;
}
}
else{
if(p['M']>0){
p['M']--;
//这个T可以在任何位置,存储需要的t。
cnt++;
}
}
}
p['T']-=cnt;
if(p['T']!=0||p['M']!=0)flag=false;
if(flag)puts("YES");
else puts("NO");
}
int main(){
while(cin>>t){
while(t--){
cin>>n>>s;
solve();
}
}
return 0;
}

C. The Sports Festival

  • 解题思路
    这道题非常有意思。我们来看,Codeforces Round #715 (Div. 2) A~C题解_c代码_02,单看这个可能难以发现什么。那么我们直接可以看Codeforces Round #715 (Div. 2) A~C题解_算法_03,这个值是已经确定了的,即是所有成员的最大速度和最小速度之差,有了这个初始值,我们就好分析了,直接从初始值下手,也就是逆着来看整个过程。为了减小这个差值,我们有两步操作可以选择:
  • 剔除当前最小值。
  • 剔除当前最大值。

这种决策问题正好提示了我们需要使用动态规划来解决问题,即哪一步最优。我们先要表示状态,既然是剔除,我们就可以用Codeforces Round #715 (Div. 2) A~C题解_c代码_04来表示剔除了Codeforces Round #715 (Div. 2) A~C题解_算法_05个最大值,Codeforces Round #715 (Div. 2) A~C题解_算法_06个最小值的速度之差,这个值表示的意思就是累加了从Codeforces Round #715 (Div. 2) A~C题解_动态规划_07的速度差值。那么初始状态自然就是Codeforces Round #715 (Div. 2) A~C题解_c代码_08(下标从0开始)
那么对于状态转移方程其实就已经好确定了,Codeforces Round #715 (Div. 2) A~C题解_动态规划_09,为什么是这样呢?因为Codeforces Round #715 (Div. 2) A~C题解_c代码_04是由Codeforces Round #715 (Div. 2) A~C题解_动态规划_11或者Codeforces Round #715 (Div. 2) A~C题解_算法_12转移过来的,所以对于Codeforces Round #715 (Div. 2) A~C题解_动态规划_11,它需要删除最大值,那么由于已经删除了Codeforces Round #715 (Div. 2) A~C题解_c代码_14个最大值,那么此时再删除一个则最大值就是Codeforces Round #715 (Div. 2) A~C题解_算法_15,最小值就是Codeforces Round #715 (Div. 2) A~C题解_最小值_16,同理对于Codeforces Round #715 (Div. 2) A~C题解_c代码_17,它需要删除最小值,那么由于已经删除了Codeforces Round #715 (Div. 2) A~C题解_动态规划_18个最小值,此时再删除一个,最小值就是Codeforces Round #715 (Div. 2) A~C题解_最小值_16,最大值就是Codeforces Round #715 (Div. 2) A~C题解_i++_20。对于Codeforces Round #715 (Div. 2) A~C题解_算法_21我们同样还需要作个约束,因为最后一定是剩余一个元素的,所以删除次数不得超过Codeforces Round #715 (Div. 2) A~C题解_最小值_22,即Codeforces Round #715 (Div. 2) A~C题解_i++_23,这也说明了最后状态就是Codeforces Round #715 (Div. 2) A~C题解_i++_24。我们这样去处理即可,注意初始化。

  • AC代码
/**
*@filename:C_The_Sports_Festival
*@author: pursuit

*@created: 2021-04-16 23:05
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2000 + 5;
const int mod = 1e9+7;

int n;
int a[maxn];
ll dp[maxn][maxn];
void solve(){
//为了更好的处理,我们需要先对数组进行升序排列,这样可以好确定最小值和最大值。
sort(a,a+n);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
dp[i][j]=1e12;//初始dp数组保留最大值。
}
}
//初始化dp数组。
dp[0][0]=a[n-1]-a[0];//这是毋庸置疑的。
for(int i=1;i<n;i++){
//只删除最大值i次
dp[i][0]=dp[i-1][0]+a[n-i-1]-a[0];//删除最大值从右边删除,那么删除之后当前最大值就是a[n-i-1];
//只删除最小值i次
dp[0][i]=dp[0][i-1]+a[n-1]-a[i];//删除最小值从左边删除,那么删除之后当前最小值就是a[i]。
}
//接下来开始进行状态转移取最优。
for(int i=1;i<n;i++){
for(int j=1;i+j<n;j++){
//i+j不得超过n次。
dp[i][j]=min(dp[i][j],dp[i-1][j]+a[n-i-1]-a[j]);//选择删除最大值
dp[i][j]=min(dp[i][j],dp[i][j-1]+a[n-i-1]-a[j]);//选择删除最小值
}
}
ll res=1e12;
for(int i=0;i<n;i++){
res=min(res,dp[i][n-i-1]);
}
cout<<res<<endl;
}
int main(){
while(cin>>n){
for(int i=0;i<n;i++)cin>>a[i];
solve();
}
return 0;
}


举报

相关推荐

0 条评论