Sky Inc, Programming Contest 2023(AtCoder Beginner Contest 289)—— A-E题讲解

蒟蒻来讲题,还望大家喜。若哪有问题,大家尽可提!

Hello, 大家好哇!本初中生蒟蒻讲解一下Sky Inc, Programming Contest 2023(AtCoder Beginner Contest 289)这场比赛的A-E题

===========================================================================================

A题

Problem Statement

You are given a string s consisting of two kinds of characters, 0 and 1. Print the string obtained by replacing 0 with 1 and 1 with 0 in s.

Constraints

  • The length of s is between 1 and 10, inclusive.
  • s consists of two kinds of characters, 0 and 1.

Input

The input is given from Standard Input in the following format:

s

Output

Print the answer in a single line.


思路

这道题我们就是把1转成0,把0转成1。很简单,直接见代码~~~

代码

/*
------------------Welcome to Your Code--------------
Name:
Contest:
Wishes:AK!
------------------Start Writing!!!------------------
*/
#include 
#define endl '\n'

using namespace std;

inline int read()
{
    int w = 1, s = 0;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') s = s * 10 + c - '0', c = getchar();
    
    return w * s;
}

int main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    
    string s;
    
    cin >> s;
    
    for (auto c : s)
    	cout << ((c - 1) & 1);
    
    return 0;
}

B题

Problem Statement

Studying Kanbun, Takahashi is having trouble figuring out the order to read words. Help him out!

There are N integers from 1 through N arranged in a line in ascending order.
Between them are M "レ" marks. The i-th "レ" mark is between the integer a_i and integer (a_i + 1).

You read each of the N integers once by the following procedure.

  • Consider an undirected graph G with N vertices numbered 1 through N and M edges. The i-th edge connects vertex a_i and vertex (a_i+1).
  • Repeat the following operation until there is no unread integer:
    • let x be the minimum unread integer. Choose the connected component C containing vertex x, and read all the numbers of the vertices contained in C in descending order.

For example, suppose that integers and "レ" marks are arranged in the following order:

image

(In this case, N = 5, M = 3, and a = (1, 3, 4).)
Then, the order to read the integers is determined to be 2, 1, 5, 4, and 3, as follows:

  • At first, the minimum unread integer is 1, and the connected component of G containing vertex 1 has vertices \lbrace 1, 2 \rbrace, so 2 and 1 are read in this order.
  • Then, the minimum unread integer is 3, and the connected component of G containing vertex 3 has vertices \lbrace 3, 4, 5 \rbrace, so 5, 4, and 3 are read in this order.
  • Now that all integers are read, terminate the procedure.

Given N, M, and (a_1, a_2, \dots, a_M), print the order to read the N integers.

What is a connected component?

A subgraph of a graph is a graph obtained by choosing some vertices and edges from the original graph.

A graph is said to be connected if and only if one can travel between any two vertices in the graph via edges.

A connected component is a connected subgraph that is not contained in any larger connected subgraph.

Constraints

  • 1 ≤ N ≤ 100 1 \leq N \leq 100 1N100
  • 0 ≤ M ≤ N − 1 0 \leq M \leq N - 1 0MN1
  • 1 ≤ a 1 < a 2 < ⋯ < a M ≤ N − 1 1 \leq a_1 \lt a_2 \lt \dots \lt a_M \leq N-1 1a1<a2<<aMN1
  • All values in the input are integers.

Input

The input is given from Standard Input in the following format:
N N N M M M
a 1 a 2 … a M a_{1} a_{2} \dots a_{M} a1a2aM

Output

Print the answer in the following format, where p i p_{i} pi is the i i i-th integers to read.
p 1 p 2 … p N p_{1} p_{2} \dots p_{N} p1p2pN


思路

就是,每次找到最小的没有用到的点,把他所有连接的点按降序输出出来即可~~~

代码

/*
------------------Welcome to Your Code--------------
Name:
Contest:
Wishes:AK!
------------------Start Writing!!!------------------
*/
#include 
#include 
#include 
#define endl '\n'

using namespace std;

const int N = 1e2 + 10;

int n, m;
int p;
vector<int> g[N];
vector<int> tmp;
bool st[N];

inline int read()
{
    int w = 1, s = 0;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') s = s * 10 + c - '0', c = getchar();
    
    return w * s;
}

bool cmp(int a, int b)
{
	return a > b;
}

void find(int u) //找到所有的连接的点
{
	for (auto c : g[u])
    	if (!st[c])
    		st[c] = 1, tmp.push_back(c), find(c);
}

int main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    
    cin >> n >> m;
    
    for (int i = 1; i <= m; i ++)
    	cin >> p, g[p].push_back(p + 1), g[p + 1].push_back(p);
    	
    for (int i = 1; i <= n; i ++)
    	if (!st[i]) //判断没输出过
    	{
    		tmp.clear();
    		tmp.push_back(i);
    		st[i] = 1;
    		
    		find(i);
    		
    		sort(tmp.begin(), tmp.end(), cmp); //降序排列
    		
    		for (auto c : tmp)
    			cout << c << " "; //输出
    	}
    
    return 0;
}

C题

Problem Statement

There are M M M sets, called S 1 , S 2 , … , S M S_1, S_2, \dots, S_M S1,S2,,SM, consisting of integers between 1 1 1 and N N N.
S i S_i Si consists of C i C_i Ci integers a i , 1 , a i , 2 , … , a i , C i a_{i, 1}, a_{i, 2}, \dots, a_{i, C_i} ai,1,ai,2,,ai,Ci.
There are ( 2 M − 1 ) (2^M-1) (2M1) ways to choose one or more sets from the M M M sets.
How many of them satisfy the following condition?

  • For all integers x x x such that 1 ≤ x ≤ N 1 \leq x \leq N 1xN, there is at least one chosen set containing x x x.

Constraints

1 ≤ N ≤ 10 1 \leq N \leq 10 1N10
1 ≤ M ≤ 10 1 \leq M \leq 10 1M10
1 ≤ C i ≤ N 1 \leq C_i \leq N 1CiN
1 ≤ a i , 1 < a i , 2 < ⋯ < a i , C i ≤ N 1 \leq a_{i,1} \lt a_{i,2} \lt \dots \lt a_{i,C_i} \leq N 1ai,1<ai,2<<ai,CiN
All values in the input are integers.

Input

The input is given from Standard Input in the following format:
N N N M M M
C 1 C_1 C1
a 1 , 1 a_{1,1} a1,1 a 1 , 2 a_{1,2} a1,2 … \dots a 1 , C 1 a_{1,C_1} a1,C1
C 2 C_2 C2
a 2 , 1 a_{2,1} a2,1 a 2 , 2 a_{2,2} a2,2 … \dots a 2 , C 2 a_{2,C_2} a2,C2
⋮ \vdots
C M C_M CM
a M , 1 a_{M,1} aM,1 a M , 2 a_{M,2} aM,2 … \dots a M , C M a_{M,C_M} aM,CM

Output

Print the number of ways to choose sets that satisfy the conditions in the Problem Statement.


思路

就是dfs搜索一遍,找出所有的方案。当然,可能会有重复的,比如说:1 2 3和2 1 3搜索的时候可能都会搜到,所以我们直接让枚举的集合的序列升序就行了,这样就不会出现像2 1 3这种情况~~~


代码

/*
------------------Welcome to Your Code--------------
Name:
Contest:
Wishes:AK!
------------------Start Writing!!!------------------
*/
#include 
#include 
#include 
#include 
#define endl '\n'

using namespace std;

const int N = 1e1 + 10;

int n, m;
int c[N], a[N][N];
int res;
vector<int> num;
bool st[N], flg[N];

inline int read()
{
    int w = 1, s = 0;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') s = s * 10 + c - '0', c = getchar();
    
    return w * s;
}

bool check(vector<int> x)
{
	for (int i = 1; i <= n; i ++)
		flg[i] = 0;
		
	for (auto c : x)
		flg[c] = 1;
		
	for (int i = 1; i <= n; i ++)
		if (!flg[i])
			return 0;
	return 1;
}

void dfs(int last) //last记录上一个集合序号,来确保是升序
{
	if (check(num)) //如果可以答案加1
		res ++;
	
	for (int i = 1; i <= m; i ++)
		if (!st[i] && i >= last) //条件:1.没有搜索过 2.序号是升序
		{
			st[i] = 1; //标记搜索过
			for (int j = 1; j <= c[i]; j ++)
				num.push_back(a[i][j]); //将该序列的元素加入其中
				
			dfs(i); //此时上一个集合就是i
			
			//---------回溯----------------
			
			for (int j = 1; j <= c[i]; j ++)
				num.pop_back();
			
			st[i] = 0;
		}
}

int main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    
    n = read(), m = read();
    
    for (int i = 1; i <= m; i ++)
    {
    	c[i] = read();
    	for (int j = 1; j <= c[i]; j ++)
    		a[i][j] = read();
    }
    
    dfs(0); 
    
    cout << res << endl;
    
    return 0;
}

D题

Problem Statement

There is a staircase with infinite steps.
The foot of the stairs is the 0 0 0-th step, the next step is the 1 1 1-st step, the next is the 2 2 2-nd, and so on.
There is a stair-climbing robot on the 0 0 0-th step.
The robot can climb up A 1 , A 2 , … A _ 1,A _ 2,\ldots A1,A2,, or A N A _ N AN steps at a time.
In other words, when the robot is on the i i i-th step, it can step onto one of the ( i + A 1 ) (i+A _ 1) (i+A1)-th step, ( i + A 2 ) (i+A _ 2) (i+A2)-th step, … \ldots , and ( i + A N ) (i+A _ N) (i+AN)-th step,
but not onto the others in a single step.
The robot cannot descend the stairs, either.
There are traps on the B 1 B _ 1 B1-th, B 2 B _ 2 B2-th, … \ldots , and B M B _ M BM-th steps.
Once the robot steps onto a step with a trap, it cannot move anymore.
The robot wants to step onto the X X X-th step.
Determine whether it is possible to do so.

Constraints

1 ≤ N ≤ 10 1\leq N\leq10 1N10
1 ≤ A 1 < A 2 < ⋯ < A N ≤ 1 0 5 1\leq A _ 1\lt A _ 2\lt\cdots\lt A _ N\leq10^5 1A1<A2<<AN105
1 ≤ M ≤ 1 0 5 1\leq M\leq10^5 1M105
1 ≤ B 1 < B 2 < ⋯ < B M < X ≤ 1 0 5 1\leq B _ 1\lt B _ 2\lt\cdots\lt B _ M\lt X\leq10^5 1B1<B2<<BM<X105
All values in the input are integers.

Input

The input is given from Standard Input in the following format:
N N N
A 1 A _ 1 A1 A 2 A _ 2 A2 … \ldots A N A _ N AN
M M M
B 1 B _ 1 B1 B 2 B _ 2 B2 … \ldots B M B _ M BM
X X X

Output

In a single line, print Yes if the robot can step onto the X X X-th step, and No otherwise.


思路

这道题又可以用我们的动态规划之闫氏dp分析法
Sky Inc, Programming Contest 2023(AtCoder Beginner Contest 289)—— A-E题讲解_第1张图片
这里就是有上一次转移而来(比较简单,不过多赘述啦~~~)


代码

/*
------------------Welcome to Your Code--------------
Name:
Contest:
Wishes:AK!
------------------Start Writing!!!------------------
*/
#include 
#define endl '\n'

using namespace std;

const int N = 1e5 + 10;

int n, m;
int a[N], b[N];
int st[N], f[N];
int x;

inline int read()
{
    int w = 1, s = 0;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') s = s * 10 + c - '0', c = getchar();
    
    return w * s;
}

int main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    
    n = read();
    
    for (int i = 1; i <= n; i ++)
    	a[i] = read();
    	
    m = read();
    
    for (int i = 1; i <= m; i ++)	
    	b[i] = read(), st[b[i]] = 1;
    	
    x = read();
    
    f[0] = 1; //初始化
    for (int i = 1; i <= x; i ++)
    	for (int j = 1; j <= n; j ++)
    	{
    		if (st[i]) break;
    		
    		if (i >= a[j]) f[i] |= f[i - a[j]];
    	}
    	
    (f[x]) ? puts("Yes") : puts("No");
    
    return 0;
}

E题

Problem Statement

There is a simple undirected graph with N N N vertices numbered 1 1 1 through N N N and M M M edges numbered 1 1 1 through M M M. Edge i i i connects vertex u i u_i ui and vertex v i v_i vi.
Every vertex is painted either red or blue. The color of vertex i i i is represented by C i C_i Ci; vertex i i i is painted red if C i C_i Ci is 0 0 0 and blue if C i C_i Ci is 1 1 1.
Now, Takahashi is on vertex 1 1 1 and Aoki is on vertex N N N.
They may repeat the following move zero or more times.

Each of the two simultaneously moves to a vertex adjacent to the current vertex.
Here, the vertices that Takahashi and Aoki move to must have different colors.
By repeating the move above, can Takahashi and Aoki simultaneously end up on vertices N N N and 1 1 1, respectively?

If it is possible, find the minimum number of moves required. If it is impossible, print -1.
You are given T T T at the beginning of the input. Solve the problem for T T T test cases.

Constraints

1 ≤ T ≤ 1000 1 \leq T \leq 1000 1T1000
2 ≤ N ≤ 2000 2 \leq N \leq 2000 2N2000
1 ≤ M ≤ min ⁡ ( N ( N − 1 ) 2 , 2000 ) 1 \leq M \leq \min(\frac{N(N-1)}{2}, 2000) 1Mmin(2N(N1),2000)
C i ∈ { 0 , 1 } C_i \in \lbrace 0, 1 \rbrace Ci{0,1}
1 ≤ u i , v i ≤ N 1 \leq u_i, v_i \leq N 1ui,viN
The graph given in the input is simple.
All values in the input are integers.
The sum of N N N over all test cases does not exceed 2000 2000 2000.
The sum of M M M over all test cases does not exceed 2000 2000 2000.

Input

The input is given from Standard Input in the following format, where test i \text{test}_i testi denotes the i i i-th test case:
T T T
test 1 \text{test}_1 test1
test 2 \text{test}_2 test2
⋮ \vdots
test T \text{test}_T testT

Each test case is given in the following format:
N N N M M M
C 1 C_1 C1 C 2 C_2 C2 … \dots C N C_N CN
u 1 u_1 u1 v 1 v_1 v1
u 2 u_2 u2 v 2 v_2 v2
⋮ \vdots
u M u_M uM v M v_M vM

Output

Print T T T lines. The i i i-th line should contain the answer to the i i i-th test case.

For each test case, print the minimum number of moves required for Takahashi and Aoki to simultaneously end up in vertices N N N and 1 1 1, respectively, if it is possible, and -1 otherwise.


思路

我们可以用一个bfs来计算每次两个人的位置,只要到终点就说明可以了,返回即可~~~

代码

#include 
#include 
#include 
#define ll long long

using namespace std;


inline int read()
{
    int w = 1, s = 0;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') s = s * 10 + c - '0', c = getchar();
    
    return w * s;
}

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

    ll t = 1;
    cin >> t;
    while (t--)
    {
        ll n, m;
        cin >> n >> m;
        vector<ll> clr(n + 1);
        
        for (ll x = 1; x <= n; x++)
            cin >> clr[x];
        
        vector<vector<ll>> g(n + 1); //存边
        for (ll a, b, x = 0; x < m; x++) {
            cin >> a >> b;
            g[a].push_back(b);
            g[b].push_back(a);
        }
        
        if (clr[1] == clr[n]) {
            cout << -1 << '\n';
            continue;
        }
        
        queue<pair<ll, pair<ll, ll>>> q; //第一个参数表示步数,第二个中的两个分别表示Takahashi的位置和Aoki的位置
        q.push({0, {1, n}}); //起点步数为0
        vector<vector<bool>> st(n + 10, vector<bool>(n + 10, 0)); //记录有没有走过
        st[1][n] = 1; //上来起点设为走过
        ll res = -1;
        
        while (!q.empty()) {
        	
            auto tmp = q.front(); //bfs模板
            q.pop();
            
            ll ct = tmp.first, tid = tmp.second.first, aid = tmp.second.second; //分别取出,每一个数
            
            if (tid == n and aid == 1) { //如果到达终点,直接退出
                res = ct;
                break;
            }
            
            vector<ll> td, ad; //td记录Takahashi当前位置能到的点,ad记录Aoki当前位置能到的点
            for (auto c : g[tid])
                td.push_back(c);
            for (auto c : g[aid])
                ad.push_back(c);
            
            for (auto x : td)
                for (auto y : ad)
                    if (clr[x] != clr[y] and !st[x][y]) //如果颜色不同且没走过
                        st[x][y] = 1, q.push({ct + 1, {x, y}}); //记录下来
                        
    	}
    	
    	
        cout << res << '\n';
    }
    return 0;
}

今天就到这里了!

大家有什么问题尽管提,我都会尽力回答的!

吾欲您伸手,点的小赞赞。吾欲您喜欢,点得小关注!

你可能感兴趣的:(算法-搜索,算法-DFS,算法-DP,c++,开发语言)