2021年中国大学生程序设计竞赛女生专场-ADGIK

昨天写了21年CCPC的女生赛,很庆幸自己的实力居然也能拿个牌子。一共写出来了六题,前面五题都还算是签到,妥妥手速场无疑了。废话不多说,开始讲解。

A. 公交线路

题意

小Q要坐公交,从站点x到y。公交车上有广播,但是小Q只能听见每一次广播站点的字数。你需要帮助小Q判定他是否坐反路线了。

思路

其实三个样例就已经对应了三种情况了。1.正确的 2.错误 3.不确定 ; 而出现第三种状况当且仅当存在以x为中心,左右两面念出来的字数是一样的。我们优先判定这种情况。然后在判断从x到y的各个站点的字数和小Q听到的一不一样就可以了。需要注意的是x和y的大小关系是不一定的。

代码

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include <iomanip>  
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 2000007;
const int INF = 0x3f3f3f;
const int mod = 1e9 + 7;
const double pi = acos(-1); 
inline ll read(){
	ll x = 0, f = 1; char ch; ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int n,x,y,m;
bool flag;
int luxian[15],ting[15];
bool isok()
{
    int u=m;
    int l,r;
    for(int i=1;i<=m;i++)
   {
        l=x-i,r=x+i;
        if(luxian[l]==luxian[r])
        {
            continue;
        }
        else
        {
            return true;
        }
   }
   return false;
}
void solve() 
{
    n=read(),x=read(),y=read();
    for(int i=1;i<=n;i++)
    {
        luxian[i]=read();
    }
    m=read();
    for(int i=1;i<=m;i++)
    {
        ting[i]=read();
    }
    if(!isok())
    {
        cout<<"Unsure"<<Endl;
    }
    else if(isok()&&x<y)
    {
        flag=1;
       for(int i=1;i<=m;i++)
       {
           int j=x+i;
         if(ting[i]==luxian[j])
         {
           continue;
         }
         else
         {
            flag=0;
            break;
         }
       }
       if(flag) cout<<"Right"<<Endl;
       else cout<<"Wrong"<<Endl;
    }
    else
    {
       flag=1;
        for(int i=1;i<=m;i++)
       {
            int j=x-i;
         if(ting[i]==luxian[j])
         {
           continue;
         }
         else
         {
            flag=0;
            break;
         }
       }
       if(flag) cout<<"Right"<<Endl;
       else cout<<"Wrong"<<Endl;
    }
}
 
int main() {
//for(int T = read(); T; T--)
		solve();
	return 0;
} 

D. 修建道路

题意

n个村庄,修n-1条双向道路,要求所有村庄都能互相到达。修路的花费是,如果要修从村庄i到j的路的话,那么花费是max{ak} k介于i和j之间。要求输出最少花费。

思路

区间越短,那么取到更大的数的概率也就越小。例如修村庄4到5的花费必然小于等于村庄4到6的花费。所以花费最少必然是从1到n按顺序串联起来:

那么答案就为连续相邻区间最大值的和。

代码

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include <iomanip>  
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 2000007;
const int INF = 0x3f3f3f;
const int mod = 1e9 + 7;
const double pi = acos(-1); 
inline ll read(){
	ll x = 0, f = 1; char ch; ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
ll n,ans,x;
ll a[200005];
void solve() 
{
    ans=0;
    n=read();
    for(ll i=1;i<=n;i++)
    {
        a[i]=read();
        if(i>=2)
        {
            x=max(a[i],a[i-1]);
            ans+=x;
        }
    }
    cout<<ans;
}
 
int main() {
//for(int T = read(); T; T--)
		solve();
	return 0;
} 

G. 3G网络

题意

建立n个3G基站,每个基站覆盖面积是半径为R的圆。给定n,求所有基站覆盖面积/每个基站覆盖面积之和。

思路

题目给了一个很关键的提示:

当r趋向于正无穷时,每个基站的覆盖面积都是无限大的,那么必然所有的圆都会相互覆盖,所以最后所有基站的覆盖面积可以看成是一个基站的覆盖面积S,每个基站的覆盖面积之和则为nS,所以直接输出1/n即可。

代码

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include <iomanip>  
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 2000007;
const int INF = 0x3f3f3f;
const int mod = 1e9 + 7;
const double pi = acos(-1); 
inline ll read(){
	ll x = 0, f = 1; char ch; ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
double n;
struct node{
    int x;
    int y;
}q[2005];
void solve() 
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        q[i].x=read(),q[i].y=read();
    }
    double ans=1.0/n;
    printf("%.15lf",ans);
}
 
int main() {
//for(int T = read(); T; T--)
		solve();
	return 0;
} 

I. 驾驶卡丁车

题意

一道驾驶卡丁车的模拟+搜索题。有四个指令控制车头方向和车速,卡丁车可以向8个方向进行前进v步,直至出界、撞车、穿模

思路

这道题在寒假集训的时候写过,我记得当时这题我写了特别特别久,怎么改都改不对。现在能轻松拿下来也算是进步了吧。

直接按照题意模拟即可。

首先卡丁车有两个状态参数一个是速度v,一个是车头朝向c。其次,拥有4种指令:

/* 车头朝向与c的值
 2  1  8
 3     7
 4  5   6
*/
void l()
{
    if(c==8)
        c=1;
    else c+=1;
}
void r()
{
    if(c==1)
        c=8;
    else c-=1;
}
void u()
{
    v+=1;
}
void d()
{
    v=max(v-1,0);
}

利用bfs的知识来模拟卡丁车走的情况:

void rush()
{
    int xt,yt;
    xt=x,yt=y;
    for(int i=1;i<=v;i++)
    {
   //     cout<<"now"<<xt<<" "<<y<<Endl;
        xt+=dist[c-1][0];
        yt+=dist[c-1][1];
  //      cout<<"now dist[c-1][0]"<<dist[c-1][0]<<" "<<dist[c-1][1]<<Endl;
    //    cout<<xt<<" "<<yt<<Endl;
    //    cout<<"over"<<Endl;
        if(!iscrash(xt,yt))
        {
            v=0;
            cout<<"Crash! "<<x<<" "<<y<<Endl;
            return ;
        }
        else
        {
            x=xt,y=yt;
        }
    }
    cout<<x<<" "<<y<<Endl;
}

判定是否crash,有三种情况:1.撞到障碍物 2.出界 3.穿模

bool iscrash(int x,int y)
{
    if(v==0) 
        return true;
    else
    {
   //     cout<<"---iscrash----"<<Endl;
  //      cout<<x<<" "<<y<<" "<<c<<Endl;
        if(x<=0||x>n||y<=0||y>m)
        {
   //         cout<<"here1"<<Endl;
            return false;
        }
        else if(mp[x][y]=='#')
        {
   //         cout<<"here2"<<Endl;
            return false;
        }
        else if(c==8&&mp[x][y-1]=='#'&&mp[x+1][y]=='#')
        {
   //         cout<<"here3"<<Endl;
            return false;
        }
        else if(c==2&&mp[x][y+1]=='#'&&mp[x+1][y]=='#')
        {
   //         cout<<"here4"<<Endl;
            return false;
        }
        else if(c==4&&mp[x-1][y]=='#'&&mp[x][y+1]=='#')
        {
  //          cout<<"here5"<<Endl;
            return false;
        }
        else if(c==6&&mp[x][y-1]=='#'&&mp[x-1][y]=='#')
        {
  //          cout<<"here6"<<Endl;
            return false;
        }
        else return true;
    }
    
}


至此,问题基本解决。

代码

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include <iomanip>  
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 2000007;
const int INF = 0x3f3f3f;
const int mod = 1e9 + 7;
const double pi = acos(-1); 
inline ll read(){
	ll x = 0, f = 1; char ch; ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int n,m,q,x,y;
int v,c;
char mp[55][55];
string zl;
int dist[8][2]={{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1}};
void l()
{
    if(c==8)
        c=1;
    else c+=1;
}
void r()
{
    if(c==1)
        c=8;
    else c-=1;
}
void u()
{
    v+=1;
}
void d()
{
    v=max(v-1,0);
}

bool iscrash(int x,int y)
{
    if(v==0) 
        return true;
    else
    {
   //     cout<<"---iscrash----"<<Endl;
  //      cout<<x<<" "<<y<<" "<<c<<Endl;
        if(x<=0||x>n||y<=0||y>m)
        {
   //         cout<<"here1"<<Endl;
            return false;
        }
        else if(mp[x][y]=='#')
        {
   //         cout<<"here2"<<Endl;
            return false;
        }
        else if(c==8&&mp[x][y-1]=='#'&&mp[x+1][y]=='#')
        {
   //         cout<<"here3"<<Endl;
            return false;
        }
        else if(c==2&&mp[x][y+1]=='#'&&mp[x+1][y]=='#')
        {
   //         cout<<"here4"<<Endl;
            return false;
        }
        else if(c==4&&mp[x-1][y]=='#'&&mp[x][y+1]=='#')
        {
  //          cout<<"here5"<<Endl;
            return false;
        }
        else if(c==6&&mp[x][y-1]=='#'&&mp[x-1][y]=='#')
        {
  //          cout<<"here6"<<Endl;
            return false;
        }
        else return true;
    }
    
}
void rush()
{
    int xt,yt;
    xt=x,yt=y;
    for(int i=1;i<=v;i++)
    {
   //     cout<<"now"<<xt<<" "<<y<<Endl;
        xt+=dist[c-1][0];
        yt+=dist[c-1][1];
  //      cout<<"now dist[c-1][0]"<<dist[c-1][0]<<" "<<dist[c-1][1]<<Endl;
    //    cout<<xt<<" "<<yt<<Endl;
    //    cout<<"over"<<Endl;
        if(!iscrash(xt,yt))
        {
            v=0;
            cout<<"Crash! "<<x<<" "<<y<<Endl;
            return ;
        }
        else
        {
            x=xt,y=yt;
        }
    }
    cout<<x<<" "<<y<<Endl;
}
void solve() 
{
    n=read(),m=read();
    v=0,c=1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            cin>>mp[i][j];
            if(mp[i][j]=='*')
            {
                x=i;
                y=j;
            }
        }
    q=read();
    cin>>zl;
    for(int i=0;i<q;i++)
    {
        if(zl[i]=='L')
        {
            l();
        }
        else if(zl[i]=='R')
        {
            r();
        }
        else if(zl[i]=='U')
        {
            u();
        }
        else
        {
            d();
        }
        rush();
    }
}
 
int main() {
//for(int T = read(); T; T--)
		solve();
	return 0;
} 

K. 音乐游戏

题意

过于水的签到题了。

思路

直接统计-的个数即可。

代码

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include <iomanip>  
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 2000007;
const int INF = 0x3f3f3f;
const int mod = 1e9 + 7;
const double pi = acos(-1); 
inline ll read(){
	ll x = 0, f = 1; char ch; ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int n;
char s;
int ans;
void solve() 
{
    ans=0;
    n=read();
    for(int i=1;i<=n;i++)
    {
        getchar();
        for(int j=1;j<=6;j++)
        {
            scanf("%c",&s);
            if(s=='-')
            {
                ans++;
            }
        }
    }
    cout<<ans<<Endl;
}
 
int main() {
//for(int T = read(); T; T--)
		solve();
	return 0;
} 
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值