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

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

 K - 音乐游戏

思路:签到题,数有多少'-'

#include<bits/stdc++.h>
using namespace std;
#define int long long
vector<int>d[5010];

int32_t main(){
    int n;
    cin>>n;
    int ans=0;
    getchar();
    for(int i=1;i<=n;i++){
        string s;
        getline(cin,s);
        for(int i=0;i<s.length();i++){
            if(s[i]=='-'){
                ans++;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}
View Code

G - 3G网络

思路:签到题,当r无穷大,所有圆所占范围近似相同,那么答案为1/n

#include<bits/stdc++.h>
using namespace std;
#define int long long

int32_t main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        int x,y;
        cin>>x>>y;
    }
    printf("%.15lf",1.0/n);
    return 0;
}
View Code

D - 修建道路

思路:签到题,连n-1条边让n个点相通,且连接i和j需要花费max{ak}(i<=k<=j);对于点i,要与1~i-1连一条边,那么一定是连i-1,若存在ak<ai-1(k<i-1),由于要取max,那么一定取不到ak,若存在ak>ai-1(k<i-1),那么取i-1是最优的,所以i一定是连i-1,且连完一定保证n个点相通。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[200010];

int32_t main(){
    int n;
    cin>>n;
    int ans=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(i>=2)
            ans+=max(a[i],a[i-1]);
    }
    cout<<ans<<endl;
    return 0;
}
View Code

A - 公交线路

思路:签到题,判断下是否超过范围,在分别判两个方向是否正确

#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=5e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;


void solve(){
    int n,x,y;cin>>n>>x>>y;
    vector<int>a(n+1);
    for(int i=1;i<=n;++i)cin>>a[i];
    int k;cin>>k;
    vector<int>b(k+1);
    for(int i=1;i<=k;++i)cin>>b[i];
    bool r=true,l=true;
    if(x+k>n)r=false;
    if(x-k<1)l=false;
    for(int i=1,il=x-1,ir=x+1;i<=k;++i){
        if(r&&b[i]!=a[ir++])r=false;
        if(l&&b[i]!=a[il--])l=false;
    }
    if(r&&l)cout<<"Unsure";
    else if((x<y&&r)||(x>y&&l))cout<<"Right";
    else cout<<"Wrong";
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
    return 0;
}
View Code

I - 驾驶卡丁车

思路:模拟题,模拟每一步的速度,方向

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
int dx[8]= {-1,-1,0,1,1,1,0,-1};
int dy[8]= {0,1,1,1,0,-1,-1,-1};
int32_t main(){
    int n,m;cin>>n>>m;
    string g[55];
    int sx,sy;
    for(int i=1;i<=n;++i){
        string s;
        cin>>s;
        g[i]=' '+s;
        for(int j=1;j<=m;++j)
            if(g[i][j]=='*')sx=i,sy=j;
    }
    int q,v=0,dir=0;cin>>q;
    string s;
    cin>>s;
    for(int i=0;i<q;++i){
        if(s[i]=='U')v++;
        else if(s[i]=='D')v=max(v-1,0ll);
        else if(s[i]=='L')dir--,dir=(dir+8)%8;
        else dir++,dir%=8;
        bool ok=false;
        for(int j=1;j<=v;++j){
            int x=sx+dx[dir],y=sy+dy[dir];
            if(dir==0||dir==2||dir==4||dir==6){
                if(x<1||x>n||y<1||y>m||g[x][y]=='#'){
                    v=0,ok=true;break;
                }
                else sx=x,sy=y;
            }else if(dir==7){
                if(x<1||x>n||y<1||y>m||g[x][y]=='#'){
                    v=0,ok=true;break;
                }
                int x1=sx+dx[dir-1],y1=sy+dy[dir-1];
                int x2=sx+dx[0],y2=sy+dy[0];
                if(g[x1][y1]=='#'&&g[x2][y2]=='#'){
                    v=0,ok=true;break;
                }
                sx=x,sy=y;
            }else{
                if(x<1||x>n||y<1||y>m||g[x][y]=='#'){
                    v=0,ok=true;break;
                }
                int x1=sx+dx[dir-1],y1=sy+dy[dir-1];
                int x2=sx+dx[dir+1],y2=sy+dy[dir+1];
                if(g[x1][y1]=='#'&&g[x2][y2]=='#'){
                    v=0,ok=true;break;
                }
                sx=x,sy=y;
            }
        }

        if(ok)cout<<"Crash! ";
        cout<<sx<<' '<<sy<<'\n';
    }
    return 0;
}
View Code

C - 连锁商店

思路1:状态dp,由于n<=36,若每个公司都有多个商店,且最多有18个公司需要考虑购买哪个商店的问题,可以用2进制表示有多商店的公司的情况,将多商店的公司离散化到二进制数的位数,(二进制数当前位为1表示该公司已购买,0表示没购买),将多商店的公司离散化成二进制数位数,其他的商店直接购买,那么就可以用dp来求每个景点的最大花费;

fa[i]表示景点i属于哪家公司,w[i]表示公司i的卖价,now[i]表示公司i表示二进制数的位数;

f[i][j]表示第i个景点当前多商店公司的购买情况为j的最大花费,

若第i个景点的公司不含其他商店:f[i][j]=max(f[i][j],f[k][j]+w[fa[j]])

否则:若j的now[i]位为0,则f[i][j|(1<<now[i])]=max(f[i][j|(1<<now[i])],f[k][j]+w[fa[j]]);若j的now[i]位为1,则f[i][j]=max(f[i][j],f[k][j]);

B - 攻防演练

思路:将串按每部分至少一个含所有的m个字符划开,(除最后一部分外),如aabc|abc|abbc|c,可以看出答案为4;因为每一部分可以代表构造的串的每一位的所有情况,从前开始每跳一个部分,当跳到r外,跳的次数加一即为构造的最短串长度。可以预处理出位置i后第一个字符j出现的位置,再求出i位置后所有m个字符第一次出现的位置的最大值(即为每一部分的分界线),那么求l~r跳多少步可以线性的跳,但是O(n2)的;

这里可以用倍增,f[i][j]表示从i位置开始跳2j步到达的位置,那么j最大18,j从大到小判断是否跳到r外并对步数进行累加,便可求出答案

#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=1e3+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;

void solve(){
    int m,n;cin>>m>>n;
    string s;
    cin>>s;s.insert(s.begin(),' ');
    vector<vector<int>>f(n+5,vector<int>(30));
    vector<int>pos(30,n+1);
    for(int i=0;i<=18;++i)f[n+1][i]=n+1;
    for(int i=n;i>=0;--i){
        for(int j=0;j<m;++j)f[i][0]=max(f[i][0],pos[j]);
        if(i)pos[s[i]-'a']=i;
    }
    for(int i=1;i<=18;++i)
        for(int j=0;j<=n;++j)
            f[j][i]=f[f[j][i-1]][i-1];

    int q;cin>>q;
    while(q--){
        int ans=0,l,r;cin>>l>>r;
        l--;
        for(int i=18;i>=0;--i){
            if(f[l][i]<=r){
                l=f[l][i];
                ans+=1ll<<i;
            }
        }
        ans++;
        cout<<ans<<'\n';
    }
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T=1;
    //cin>>T;
    while(T--){
        solve();
    }
    return 0;
}
View Code

 

posted @ 2023-09-26 21:05  bible_w  阅读(24)  评论(0编辑  收藏  举报