AtCoder Beginner Contest 404 A-E 题解

在这里插入图片描述

还是ABC好打~比ARC好打多了(

题解部分

A - Not Found

给定你一个长度最大25的字符串,任意输出一个未出现过的小写字母

签到题,map或者数组下标查询一下就好

#include<bits/stdc++.h>

using namespace std;

#define int long long
#define lowbit(x) x&(-x)

const int MOD=1e9+7;
const int N=1000100;

int a[N];

void solve() {
    init();

    string s;
    cin>>s;
    map<char,int>mp;
    int len = s.length();
    for(int i=0;i<len;i++) {
        mp[s[i]]=1;
    }

    for(int i=0;i<26;i++) {
        if(!mp[(char)('a'+i)]) {
            cout<<(char)('a'+i);
            return ;
        }
    }
}

signed main() {
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);


    //cout<<prime[cnt-1]<<"\n";
    //for(int i=1;i<=cnt;i++) cout<<prime[i]<<"\n";

    int t=1;
    //cin>>t;
    while(t--) {
        solve();
    }
    return 0;
}

B - Grid Rotation

给定两个二维字符数组,你能进行两种操作:将第一个字符数组顺时针旋转90度或者将第一个字符数组任意位置改为任意字符,问你最少需要多少次操作能将第一个字符数组变成第二个字符数组

纯模拟题,单独封装一个函数用于数组的旋转即可(不会有人真的手动写完旋转后的数组吧)

代码如下:

#include<bits/stdc++.h>

using namespace std;

#define int long long
#define lowbit(x) x&(-x)

const int MOD=1e9+7;
const int N=1000100;

int a[N];

char b[110][110];
char c[110][110];
char t[110][110];

int n;

int minvalue = MOD;

void rev() {
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            c[i][j] = b[n-j+1][i];
        }
    }
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++)
            b[i][j] = c[i][j];
    }
}

void solve() {
    init();

    cin>>n;

    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) cin>>b[i][j];
    }
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) cin>>t[i][j];
    }

    for(int i=1;i<=4;i++) {
        int sum=0;
        for(int j=1;j<=n;j++) {
            for(int k=1;k<=n;k++) {
                if(b[j][k] != t[j][k]) sum++;
            }
        }
        //cout<<sum<<"\n";
        minvalue = min(minvalue,sum + i - 1);
        rev();
    }
    cout<<minvalue<<"\n";
}

signed main() {
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);


    //cout<<prime[cnt-1]<<"\n";
    //for(int i=1;i<=cnt;i++) cout<<prime[i]<<"\n";

    int t=1;
    //cin>>t;
    while(t--) {
        solve();
    }
    return 0;
}

C - Cycle Graph?

给定你n个节点m条边,问你这个图是否有且仅有一条连接所有节点的欧拉回路

很简单,只要满足有n条边,每个点都是联通的并且每个点都有两条边就行

代码如下:

#include<bits/stdc++.h>

using namespace std;

#define int long long
#define lowbit(x) x&(-x)

const int MOD=1e9+7;
const int N=1000100;

void init() {

}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int Base = uniform_int_distribution<>(8e8,9e8)(rng);

int a[N];

vector<int>G[N];
int num;
int vis[N];

void dfs(int t){
    vis[t]=1;
    num++;

    for(int i=0;i<G[t].size();i++) {
        int son = G[t][i];

        if(!vis[son]) {
            dfs(son);
        }
    }
    if(G[t].size() != 2) num = MOD;
}

void solve() {
    init();

    int n,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++) {
        int u,v;
        cin>>u>>v;
        G[u].push_back(v);
        G[v].push_back(u);
    }

    if(m != n) {
        cout<<"No\n";
        return ;
    }

    dfs(1);
    if(num != n) cout <<"No\n";
    else cout<<"Yes\n";
}

signed main() {
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);


    //cout<<prime[cnt-1]<<"\n";
    //for(int i=1;i<=cnt;i++) cout<<prime[i]<<"\n";

    int t=1;
    //cin>>t;
    while(t--) {
        solve();
    }
    return 0;
}

D - Goin’ to the Zoo

有n个动物园以及m个动物,告诉你每个动物在哪些动物园都有,每次去第i个动物园都需要支付 C i C_i Ci元,多次去同一个动物园看同一个动物视为看了某个动物多次,问你最少需要多少元能够满足每个动物至少都看了两次

刚开始我只想着简单的做法,所以小卡了一手这个地方,后面看范围越看越感觉能暴力。仔细一算,3的10次方大概1e4,完全可以直接爆搜,然后就用爆搜的做法过了

由于每个动物只需要看两次,也就是说我最多去同一个动物园两次,所以我只需要暴力搜索去某个动物园2次,1次,0次的情况就好

代码如下:

#include<bits/stdc++.h>

using namespace std;
#define int long long 
const int N=1000100;
const int MOD=1e9+7;
vector<int>G[N];
vector<int>H[N];
int vis[N];
int n,m;
int minvalue = 20 * MOD;
int cost;
int a[N];

void dfs(int t)
{
	//cout<<t<<"||"<<cost<<"\n";
	if(t == n+1)
	{
		int sign=1;
		for(int i=1;i<=m;i++)
		{
			if(vis[i] < 2)
			{
				sign = 0;
				break;
			}
		}
		
		if(sign) minvalue = min(minvalue,cost);
		return ;
	}
	
	//去两次动物园的情况 
	for(int i=0;i<G[t].size();i++)
	{
		int v = G[t][i];
		vis[v]+=2;
	}
	cost += a[t] * 2;
	dfs(t+1);
	cost -= a[t];//去一次动物园的情况 
	for(int i=0;i<G[t].size();i++)
	{
		int v = G[t][i];
		vis[v]--;
	}
	dfs(t+1);
	cost -= a[t];//去零次动物园的情况 
	for(int i=0;i<G[t].size();i++)
	{
		int v = G[t][i];
		vis[v]--;
	}
	dfs(t+1);
}

void solve()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	
	map< pair<int,int> , int>mp;
	for(int i=1;i<=m;i++)
	{
		int num;
		cin>>num;
		for(int j=1;j<=num;j++)
		{
			int v;
			cin>>v;
			if(!mp[{v,i}]) G[v].push_back(i),mp[{v,i}]=1;
		}
	}
	
//	for(int i=1;i<=n;i++)
//	{
//		for(int j=0;j<G[i].size();j++) cout<<G[i][j]<<" ";
//		cout<<"\n";
//	}
	dfs(1);
	cout<<minvalue;
}

signed main()
{
	int t=1;
	while(t--)
	{
		solve();
	}
	return 0;
}

E - Bowls and Beans

给你n个碗,每个碗都有一个对应的 C i C_i Ci,初始时候每个碗里面都有 a i a_i ai个豆,每次操作你都可以将某个碗里面豆移动到这个碗左边 C i C_i Ci个碗中,问你最少需要多少次操作能够将所有豆移动到第一个碗里面

关于这道题我们需要理清一下思绪,首先先看某一个豆移动到第一个碗的操作,我每次遍历我当前能够到达的范围范围1,然后再遍历这个范围1,找到这个范围里面每个碗能够移动的最左边得到范围2,然后再让范围1扩张为范围2,重复操作,我所进行的操作次数就是只看这一个豆的情况下所需要的操作次数

那可能就有人要问了,为什么不是bfs去找层次呢,所以接下来就是重点,当我多个豆到达同一个碗,接下来我只需要一次操作就能将这些豆移走,也就是说我知道多个豆在哪个位置进入同一个碗,这是bfs难以做到的一点

考虑到以上这一点,我们不难得知一点:当左边的豆已经找到最短移动到第一个碗的时候,对于当前这个豆,我们只需要用最少的操作次数移动到前面已经找到最短移动路径即可

那么我们代码部分应该如何打呢,那我们就需要从左边开始遍历,当这个碗里面有豆的时候,我们不断重复前面提到的只看某一个豆的移动,一直重复到我可以移动到第一个碗或者是已经找到最短路径的碗即可

代码如下:

#include<bits/stdc++.h>

using namespace std;

#define int long long
#define lowbit(x) x&(-x)

const int MOD=1e9+7;
const int N=1000100;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int Base = uniform_int_distribution<>(8e8,9e8)(rng);

int a[N];
int c[N];

void solve() {
    init();

    int n;
    cin>>n;
    for(int i=1;i<=n-1;i++) cin>>c[i];
    for(int i=1;i<=n-1;i++) cin>>a[i];

    int res=0;
    int pre=0;
    for(int i=1;i<=n;i++) {
        if(a[i]) {
            int left = i,right=i;
            while(left > pre) {
                res ++;
                int nxtleft=left;
                for(int j=left;j<=right;j++) {
                    nxtleft = min(nxtleft,j - c[j]);
                }
                left = nxtleft;
            }
            pre = i;
        }
    }
    cout<<res<<"\n";
}

signed main() {
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);


    //cout<<prime[cnt-1]<<"\n";
    //for(int i=1;i<=cnt;i++) cout<<prime[i]<<"\n";

    int t=1;
    //cin>>t;
    while(t--) {
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值