zoukankan      html  css  js  c++  java
  • 中国计量大学同步赛补题

    B题:

    给一个又A和B组成的字符串

    使用魔法选择一个字典序不递增的子串, 然后使得这个子串变成字典序不递减的子串

    求使用至多依次魔法后,这个字符串能够出现的最长的字典序不递减的子串的长度为多少。

    思路:

    将连续的A和连续的B统计其数量,然后答案即为连续三个或四个A和B的数量和

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=2e5+5;
    
    int n,m;
    int a[200005];
    int main(){
        int n;
        string s;
        cin>>n;
        cin>>s;
        vector< pair<int,int> > v;
        bool flag=1;
        int cnt=0;//1代表A
        for(int i=0;i<n;i++){
            if(('A'==s[i])==flag){
                cnt++;
            }else{
                v.push_back({flag,cnt});
                cnt=1;
                flag^=1;
            }
        }
        v.push_back({flag,cnt});
        v.push_back({0,0});
        v.push_back({0,0});
        v.push_back({0,0});
        int ans=v[0].second;
        for(int i=0;i<v.size()-3;i++){
            if(v[i].first==1)
            ans=max(ans,v[i].second+v[i+1].second+v[i+2].second+v[i+3].second);
            else
            ans=max(ans,v[i].second+v[i+1].second+v[i+2].second);
        }
        cout<<ans<<endl;
    }

    C题:

    白浅获得了一个仅由A和B组成的字符串。他可以至多使用一次魔法来改变字符串。

    魔法:选择一个子串,满足子串中 A 的数量等于 B 的数量,然后按字典序从小到大排序这个子串,即变成形如AAA...AAABBB...BBB这样的字符串(A和B的数量均与原来的子串相同)。

    他想知道,在他至多使用一次魔法后,这个字符串能够出现的最长的字典序不递减的子串的长度为多少。

    思路:

    统计每个数前面有多少个连续的A,后面有多少个连续的B。

    然后统计字符串的前缀和,前缀和相同说明这段区间A和B个数是相等的

    再加上左边的A和右边的B就是这段区间修改后的可以达到的最大长度

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    int n,ans=0;
    char ch;
    char a[200005];
    int preA[200005],sufB[200005];
    map<int,int>mp;
    int main(){
        cin>>n;
        //n=2e5
        for(int i=1;i<=n;i++)
            cin>>a[i];
        for(int i=1;i<=n;i++){
            if(a[i]=='A')
                preA[i]=preA[i-1]+1;
            ans=max(ans,preA[i]);
        }
        for(int i=n;i>=1;i--){
            if(a[i]=='B')
                sufB[i]=sufB[i+1]+1;
            ans=max(sufB[i],ans);
        }
        int dif=0;
        for(int i=1;i<=n;i++){
            if(a[i]=='A')
                dif++;
            else
                dif--;
            if(mp[dif]==0)
                mp[dif]=i;
            else{
                ans=max(ans,i-mp[dif]+preA[mp[dif]]+sufB[i+1]);
            }
        }
        cout<<ans<<endl;
    }

    I题:

    n×m的图中,左上角为(0,0),右下角为(n-1,m-1),0代表空地,1代表障碍

    求从(sx,sy)到(ex,ey)最少拐弯次数

    思路:

    bfs,选择方向优先选择和上次同向,同一端点可以访问多次,vis小于一个定值即可

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=2e5+5;
    
    int gcd(int a,int b){
        return a%b?gcd(b,a%b):b;
    }
    bool a[5005][5005];
    int n,m,sx,sy,ex,ey;
    int ans;
    bool flag=0;
    int dir[4][2]={1,0,-1,0,0,1,0,-1};
    int vis[5005][5005];
    struct node{
        int x,y,last,num;
    };
    void bfs(){
        ans=1000000;
        memset(vis,0,sizeof(vis));
        queue<node> q;
        q.push({sx,sy,-1,0});
        while(!q.empty()){
            node cnt=q.front();
            q.pop();
            if(cnt.x==ex&&cnt.y==ey){
                ans=min(ans,cnt.num);
                continue;
            }
            if(cnt.num>=ans)continue;
            if(cnt.last==-1){
                for(int i=0;i<4;i++){
                    int xx=cnt.x+dir[i][0],yy=cnt.y+dir[i][1];
                    if(xx>=0&&yy>=0&&xx<n&&yy<n&&a[xx][yy]==0){
                        vis[xx][yy]++;
                        q.push({xx,yy,i,0});
                    }
                }
            }else{
                for(int i=cnt.last;i<cnt.last+4;i++){
                    int xx=cnt.x+dir[i%4][0],yy=cnt.y+dir[i%4][1];
                    if(xx>=0&&yy>=0&&xx<n&&yy<n&&a[xx][yy]==0&&vis[xx][yy]<5){
                        vis[xx][yy]++;
                        q.push({xx,yy,i%4,cnt.num+(i==cnt.last?0:1)});
                    }
                }
            }
        }
    }
    int main(){
        cin>>n>>m>>sx>>sy>>ex>>ey;
        string s;
        for(int i=0;i<n;i++){
            cin>>s;
            for(int j=0;j<m;j++){
                a[i][j]=s[j]-'0';
            }
        }
        bfs();
        if(ans==1000000)
            cout<<-1<<endl;
        else
            cout<<ans<<endl;
    }

    F题:

    给一个n、m

    有n层,每层有一个x[i],x[i]代表这层有多少个宝物,每个宝物有一个价值

    总共可以取m个宝物

    每层只能从两边开始取

    求取得的宝物的最大价值和

    思路:

    计算每层取i个时的最大值

    背包dp,状态转移方程dp2[i][k]=max(dp2[i][k],dp2[i-1][k-j]+dp[i][j]);

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=2e5+5;
    
    int n,m;
    int x[105],c[105][105],dp[105][105],pre[105][105],dp2[105][10005];
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            cin>>x[i];
            for(int j=1;j<=x[i];j++){
                cin>>c[i][j];
                pre[i][j]=pre[i][j-1]+c[i][j];
            }
            for(int j=0;j<=x[i];j++){//枚举取多少个
                for(int k=0;k<=j;k++){//枚举上楼梯时取多少个
                    dp[i][j]=max(dp[i][j],pre[i][k]+pre[i][x[i]]-pre[i][x[i]-(j-k)]);
                }
                for(int k=m;k>=j;k--){
                    dp2[i][k]=max(dp2[i][k],dp2[i-1][k-j]+dp[i][j]);
                }
            }
        }
        cout<<dp2[n][m]<<endl;
    }
  • 相关阅读:
    1维FDTD仿真
    A Personal Selection of Books on E lectromagnetics and Computational E lectromagnetics---David B. Davidson
    怎么学习计算电磁学【QUORA】
    Legendre polynomials
    获取控件的宽和高
    Fragments (官方文档中文版)
    ViewTreeObserver简介
    第一个Cocos2d-x Lua游戏
    搭建Cocos Code IDE开发环境
    Cocos2d-js中Chipmunk引擎
  • 原文地址:https://www.cnblogs.com/xuanzo/p/14135283.html
Copyright © 2011-2022 走看看