牛客周赛 Round 37VP(DEF)

D.思维题:

若按照顺序发现很难入手,于是我们不妨先小紫,再让小红反悔即可

假设为cabababbabazbc,如果直接小紫,那么它一定以a开头,于是小红可以先把首尾的a去掉,即czbc,此时可以得到bc,于是小红把b也删了,这样小紫只可以取c了。

最小值在两边呢?

对于aba,小红无论怎么删,小紫都可以得到a,因此,我们可以得到一个结论:

若两边的字母一样,答案就是那个字母。

那么若不一样呢?

我们看看abc,对于小紫,可以变成a,于是小红一定要删了 a,同理也会把b删了,答案就是C.

假如两边没有min,dbhfncac,那么小红一定删bhfnca,此时d>c,所以答案是d.

假如两边有一个是abcddsagbw,于是小红让其变成gbw,此时小紫可以bw,于是把gb也删了,得到w.

因此,我们可以得出一个结论:答案就是较大的那一个。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
string s;
int n;
int main(){
    cin>>n>>s;
    if(n==1) cout<<s;
    else{
        if(s[0]>=s[n-1]) cout<<s[0];
        else cout<<s[n-1];
    }
}

E.分层BFS

我们可以分成4个图,dis[1010][1010][4],在每一个图中只能走一个方向。当他遇到*可以走到其他图

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
int t,n,m,dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}},tx,ty;
string s[1010];
int dis[1002][1010][4];
struct node{
    int x,y,k;
};
queue<node> q;
int main(){
    cin>>t;
    while(t--){
        cin>>n>>m;
        for(int i=0;i<n;i++) cin>>s[i];
       /* for(int i=0;i<n;i++) cout<<s[i]<<endl;*/
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                for(int k=0;k<4;k++) dis[i][j][k]=1e9;
            }
        }
        
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(s[i][j]=='S'){
                    for(int k=0;k<4;k++){
                        q.push({i,j,k});
                        dis[i][j][k]=0;
                    }
                }
                if(s[i][j]=='T'){
                    tx=i;
                    ty=j;
                }
            }
        }
        while(!q.empty()){
            node ck=q.front();
            q.pop();
            int x=ck.x,y=ck.y;
            if(s[x][y]=='.'||s[x][y]=='S'||s[x][y]=='T'){
                int xx=x+dir[ck.k][0],yy=y+dir[ck.k][1];
                if(xx<0||yy<0||xx>=n||yy>=m||s[xx][yy]=='#') continue;
                if(dis[xx][yy][ck.k]>dis[x][y][ck.k]+1){
                    dis[xx][yy][ck.k]=dis[x][y][ck.k]+1;
                    q.push({xx,yy,ck.k});
                }
            }
            else if(s[x][y]=='*'){
                for(int i=0;i<4;i++){
                    if((i^(ck.k))==1) continue;
                    int xx=x+dir[i][0],yy=y+dir[i][1];
                    if(xx<0||yy<0||xx>=n||yy>=m||s[xx][yy]=='#') continue;
                    if(dis[xx][yy][i]>dis[x][y][ck.k]+1){
                    dis[xx][yy][i]=dis[x][y][ck.k]+1;
                    q.push({xx,yy,i});
                }
                }
            }
        }
        int mi=1e9;
        for(int i=0;i<4;i++) mi=min(mi,dis[tx][ty][i]);
        if(mi>=1e9) cout<<-1<<endl;
        else cout<<mi<<endl;
    }
}

F。DP

本质上就是求一个最短的位与==0的子序列。

首先看到数据范围先去重,因为相同的&还是自己。

接下来我们令dp[i][0]表示原来的合成i的最小保留,1代表现在,不断滚动即可。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
int t,n,dp[210][2],x;
bool tong[200];
int main(){
    cin>>t;
    while(t--){
        cin>>n;
        memset(tong,0,sizeof(tong));
        memset(dp,0x3f,sizeof(dp));
        for(int i=0;i<n;i++){
            scanf("%d",&x);
            tong[x]=1;
        }
        for(int i=0;i<=200;i++){
            if(tong[i]==0) continue;
            dp[i][1]=1;
            for(int j=0;j<=200;j++){
                dp[i&j][1]=min(dp[i&j][1],dp[j][0]+1);
            }
            for(int j=0;j<=200;j++) dp[j][0]=dp[j][1];
        }
        if(dp[0][0]>n) cout<<-1<<endl;
        else cout<<n-dp[0][0]<<endl;
    }
}

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值