2019年湘潭大学程序设计竞赛(重现赛)

https://ac.nowcoder.com/acm/contest/893#question

湘潭大学的校赛 断断续续的作终于ak了 看了不少题解(菜就直说)

A   Who's better?

签到题

#include<bits/stdc++.h>
 
using namespace std;
 
int main()
{
    int n1,n2,t1,t2,s1,s2;
    cin>>n1>>t1>>s1;
    cin>>n2>>t2>>s2;
    if(n1>n2)
    {
        cout<<1;
        return 0;
    }
    if(n1<n2)
    {
        cout<<2;
        return 0;
    }
    if(t1<t2)
    {
        cout<<1;
        return 0;
    }
    if(t1>t2)
    {
        cout<<2;
        return 0;
    }
    if(s1<s2)
    {
        cout<<1;
        return 0;
    }
    if(s1>s2)
    {
        cout<<2;
        return 0;
    }
    cout<<"God";
 }

 B   Number

也是水题,直接模拟:

#include <bits/stdc++.h>
using namespace std;
 
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int ans=0;
        while(n>1){
            ans++;
            if(n%10==0) n/=10;
            else n+=1;
        }
        cout<<ans<<endl;
    }
    return 0;
}

C   Math Problem

打表发现a为等差数列,公差为192(其实可以推出来的,但是我懒

#include<bits/stdc++.h>
 
using namespace std;
 
int main()
 
{
    long long int t,l,r,sum;
    cin>>t;
    while(t--)
    {
        cin>>l>>r;
        if((l-1)%192!=0)
        l=l+192-(l-1)%192;
        r=r-(r-1)%192;
        sum=(l+r)*((r-l)/(192)+1)/2;
        cout<<sum<<endl;
    }
}

 D   Stone

这个题我一开始想到的是之前在洛谷做的一道题 仔细看一下又有不同 把握两个条件:第一是任意的两堆石子都可以合并 第二 是合并的时候耗费的体力由小的那一堆石子决定

我们假设有3堆石子 重量分别为 1 3 5

那么如果1和3先合并 耗费1点体力 然后在和5合并 那么耗费4点体力 总共耗费5点体力

但是如果3和5先合并 那么耗费3点体力 再和1合并 那么就耗费1点体力 一共耗费4点体力

两种选择的根本在于 第一种选择把第一堆石子的重量多累积了一次 这就是从小到大合并的弊端

所以我们要从大到小合并 这样所耗费的体力 就是石子重量的总和-最重的石子

#include <bits/stdc++.h>
using namespace std;
const int N=1e4+5;
typedef long long ll;
int a[N];
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        sort(a+1,a+1+n);
        ll ans=0;
        for(int i=1;i<=n-1;i++){
            ans+=a[i];
        }
        cout<<ans<<endl;
    }
    return 0;
}

E   Watermelon

要保证lililalala打扫卫生 就必须让别人吃西瓜的时候有西瓜能吃 在lililalala吃的时候没有西瓜可吃(这不是废话嘛........)

但是每个人吃的西瓜数是一个区间的(1,a[i]),所以我们维护一个区间(l,r) 代表当前能吃的西瓜数 对于每一个非lililalala的人 因为最少可以只吃1个 那么就让r--,因为最多可以吃a[i]个 就让l-=a[i]

而对于lililalala 因为他只会吃a[i]个 所以l和r都要-a[i]

当对于一个非lililalala人来说 如果r<=0,代表前面的人再怎么节约着吃也没得吃了.....就是NO

当对于lililalala来说 如果l<=0,代表前面的人疯狂吃 就可以让lililalala没得吃 那就是YES

#include<bits/stdc++.h>
 
using namespace std;
 
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m,i,a[100005],lb=0,ladd=0,l,r;
        cin>>n>>m;
        for(i=0;i<n;i++)
        {
            cin>>a[i];
            if(a[i]>lb)
            {
                lb=a[i];
                ladd=i;
            }
        }
        l=m;
        r=m;
        for(i=0;;i=(i+1)%(n))
        {
            if(i==ladd)
            {
                if(l<=0)
                {
                    cout<<"YES"<<endl;
                    break;
                }
                else
                {
                    l-=a[i];
                    r-=a[i];
                }
            }
            else
            {
                if(r<=0)
                {
                    cout<<"NO"<<endl;
                    break;
                }
                else
                {
                    r-=1;
                    l-=a[i];
                }
            }
        }
    }
}

F   Black & White

就是求 包含m个1的最长0串 和 包含m个0的最长1串 的较大值

在纸上模拟一下或者debug一下就理解了

#include <bits/stdc++.h>
using namespace std;
#define ll long long
char s[100005];
int n,m;
int fun(char ch)
{
    int cnt=0,ans=0;
    for(int i=0,j=0;i<n;i++){
        if(s[i]==ch){
            if(cnt<m) cnt++;
            else{
                while(s[j++]!=ch);
            }
        }
        ans=max(ans,i-j+1);
    }
    return ans;
}
int main()
{
    int t; scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        scanf("%s",s);
        printf("%d\n",max(fun('0'),fun('1')));
    }
    return 0;
}

G   Truthman or Fakeman

如果A说B是Truthman 那么A和B是同一个团体

如果A说B是Fakeman 那么A和B是不同的两个团体

只要将较大的那个定义为Truthman就好了

用dfs遍历连通块

如果一开始设为Truthman的团体较小 那就再dfs一遍取反

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
typedef pair<int,int> pr;
const int MAX_N=1e5+5;
int n,m,T;
int Sum,s,p;
int res[MAX_N];
vector<pr> e[MAX_N];
bool boo[MAX_N];
  
void DFS(int u,int pre);
void DFS1(int u,int pre);
int main()
{
    ios::sync_with_stdio(false);
    cin>>T;
    while(T--){
        p=1;
        memset(res,-1,sizeof(res));
        memset(boo,0,sizeof(boo));
        cin>>n>>m;
        for(int i=0;i<=n;++i)
            e[i].clear();
        int u,v,w;
        for(int i=0;i<m;++i)
        {
            cin>>u>>v>>w;
            e[u].push_back({v,w});
            e[v].push_back({u,w});
        }
        for(int i=1;i<=n&&p==1;++i)
            if(res[i]==-1){
                Sum=s=0;
                boo[i]=true;    res[i]=1;
                DFS(i,0);
                if(s+s<Sum)  DFS1(i,0);
            }
        if(p==1){
            for(int i=1;i<=n;++i)
                cout<<res[i];
            cout<<endl;
        }else   cout<<-1<<endl;
    }
     
    return 0;
}
  
void DFS(int u,int pre)
{
    ++Sum;
    if(res[u]==1)   ++s;
    int v,w;
    for(auto c:e[u])
        if(c.first!=pre){
            if(p==-1)   break;
            v=c.first;  w=c.second;
            if(res[v]!=-1){
                if((w==1&&res[v]!=res[u])||(w==0&&res[v]+res[u]!=1)){
                    p=-1;   break;
                }
            }else{
                if(w==1){
                    if(res[v]!=-1&&res[v]!=res[u])  p=-1;
                    res[v]=res[u];
                }else{
                    if(res[v]!=-1&&res[v]+res[u]!=1)    p=-1;
                    res[v]=(res[u]+1)%2;
                }
                DFS(v,u);
            }
        }
}
  
void DFS1(int u,int pre)
{
    res[u]=(res[u]+1)%2;
    for(auto c:e[u])
        if(c.first!=pre&&!boo[c.first]){
            boo[c.first]=true;
            DFS1(c.first,u);
        }
}

H Chat

分组dp

题意转化为要求女神生气度为K时能偷懒最长的时间

dp首先要有代价和价值 代价是鸽女神i个小时 价值就是鸽女神i个小时所能换来的最大时间

代价是要先求一遍的 具体看代码吧

#include<bits/stdc++.h>

using namespace std;

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m,k,w,i,j,vul[205][205],p[205],dp[205][205],it[205];
        memset(vul,0,sizeof(vul));
        memset(p,0,sizeof(p));
        memset(dp,0,sizeof(dp));
        memset(it,0,sizeof(it));
        scanf("%d%d%d",&n,&m,&k);
        int sum=n*m;
        for(i=1;i<=n;i++)
        {
            char a[205]; 
            scanf("%s",a+1);
            for(j=1;j<=m;j++)
            {
                if(a[j]=='0')
                p[j]=p[j-1];
                else
                {
                    p[j]=p[j-1]+1;
                    it[i]++;
                }        
             }
             vul[i][it[i]]=m;
             for(j=1;j<=m;j++)
                 for(w=j;w<=m;w++)
                 vul[i][it[i]-(p[w]-p[j-1])]=max(vul[i][it[i]-(p[w]-p[j-1])],m-(w-j+1));
        }
        for(i=1;i<=n;i++)
        for(j=0;j<=it[i];j++)
        for(w=k;w>=j;w--)
        {
            dp[i][w]=max(dp[i][w],dp[i-1][w-j]+vul[i][j]);
        }
        cout<<sum-dp[n][k]<<endl;
    }
}
原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/10903538.html