Have fun together in winter vacation training total review

Unblocked project

Title:

The minimum number of roads to be built so that the two towns can be connected

answer:

The
meaning of the question is very clear. Let's analyze the following example: The first line tells you that there are 4 points and 2 paths in total. The next two lines tell you that there is a road between 1 and 3, and there is a road between 4 and 3. Then the whole picture is divided into two parts 1-3-4 and 2. Just add another path, connect 2 to any other point, and the smooth project is realized, then the output result of this group of data is 1.

What should I do? You can use what you have learned and check the collection! Give each parent array an initial value of -1, which means that it has not been connected to other roads, and -1 is set every time a road is connected. Therefore, the difference from the normal union search set is that the initialization should be as follows:

for(int i=0;i<=n;i++)
    pre[i]=-1;

The Find function should be:

int Find(int x)
{
    
    
    if(pre[x]==-1) return x;
    return pre[x]=Find(pre[x]);

Then you can simply write the program. It should be noted that the number of edges that need to be created is always the number of towns minus one, and then there is always a root node that is not set to -1. The program is as follows

Code:


#include<cstdio>
int pre[1010];
int find(int a)//find函数查找他的领导 
{
    
    
	int leader=a;
	while(pre[leader]!=leader)//领导不是自己,找自己的上一级领导 
		leader=pre[leader]; 
	int t,b=a;
	while(b!=leader)
	{
    
    
		t=pre[a];
		pre[a]=leader;
		b=t;
	}
	return leader;
}
int main()
{
    
    
	int n,m,point1,point2,all,lead1,lead2;//point表示城镇编号 
	while(scanf("%d",&n),n)
	{
    
    
		all=n-1;//n个点不连成环需要n-1条边 
		for(int i=1;i<=n;i++){
    
    
			pre[i]=i;//初始化为自己的领导是自己 
		}
		scanf("%d",&m);
		for(int j=0;j<m;j++){
    
    
			scanf("%d%d",&point1,&point2);
			lead1=find(point1);
			lead2=find(point2);
			if(lead1!=lead2){
    
    
				pre[lead2]=lead1;
				all--;//根据题目给出的条件每连通一条总数减一 
			}
		}
		printf("%d\n",all);
	}
	return 0;
}

Xiaoxi's Labyrinth

answer:

This question is not difficult to do with the union search set. To judge whether it is a ring or not is to judge whether the root nodes of the two nodes to be merged are the same, so the join function is slightly changed.
It should be noted that there is another point that each room must be connected, which I ignored at first, so the sample is WA (because the sample is guaranteed to be fully connected);

Code:

#include<bits/stdc++.h>
using namespace std;
int pre[100005];
bool vis[100005];

int find(int x){
    
    
    int r = x;
    while(pre[r] != r){
    
    
        r = pre[r];
    }
    int i = x, j;
    while(i != r){
    
    
        j = pre[i];
        pre[i] = r;
        i = j;
    }
    return r;
}

bool join(int x, int y){
    
    
    int i = find(x), j = find(y);
    if (i != j){
    
    
        pre[j] = i;
        return true;
    }
    else return false;
}

int main()
{
    
    
    int a, b;
    while(scanf("%d%d", &a, &b) != EOF){
    
    
        for (int i = 1; i <= 100005; ++i) pre[i] = i;
        memset(vis, 0, sizeof(vis));
        if (a == -1 && b == -1) break;
        if (a == 0 && b == 0){
    
    
            printf("Yes\n");
            continue;
        }
        bool flag = 1;
        while(a != 0){
    
    
            vis[a] = vis[b] = 1;
            //判断是否成环
            if(!join(a, b)) flag = 0;
            scanf("%d%d", &a, &b);
        }
        int root = 0;
        //判断是否全连通
        for (int i = 1; i <= 100005; ++i)
            if (vis[i] && pre[i] == i) ++root;
        if (root > 1) flag = 0;
        if (flag) printf("Yes\n");
        else printf("No\n");
    }

    return 0;
}

Express Mail Taking

Title:

Now there are n cabinets arranged in sequence, and these cabinets are numbered from 1 to n. The distance between each cabinet is 1, and the cabinet number k is special. This is a code cabinet. To open other cabinets, you must enter the code in this cabinet. Now you have m couriers in these cabinets. You enter from the entrance and exit from the entrance after taking the courier. Ask the minimum distance you need to travel.

answer:

Greedy approach:
Since these express items are not related, this question is very simple. Before we finish picking up the express, we need to go to the password locker and enter the password before picking up the express. These steps are equivalent . So why is there a minimum distance for this question? The important thing is that when we pick up the last courier, we don’t need to return to the cipher cabinet after taking the last courier and walk directly to the exit. Therefore: the location of the last courier is extremely important and this is also a decisive factor. So we want to make the location of the last courier close to the entrance. This question is easy to solve.

Code:

#include<bits/stdc++.h>	//POJ不支持

#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair

using namespace std;

const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e6;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//

ll t,n,m,k;
ll a[maxn];
int main(){
    
    
	//freopen("in.txt", "r", stdin);//提交的时候要注释掉
	IOS;
	while(cin>>t){
    
    
		while(t--){
    
    
			cin>>n>>m>>k;
			rep(i,0,m-1){
    
    
				cin>>a[i];
			}
			sort(a,a+m);
			ll ans=k-1;
			per(i,m-1,1){
    
    
				ans+=abs((a[i]-k)*2);
			}
			if(a[0]<=k)
				ans+=k-1;
			else{
    
    
				ans+=abs((a[0]-k)*2)+k-1;
			}
			cout<<ans<<endl;
		}
	}
	return 0;
}

Reports

Title:

Give you a report on a certain day. There are a total of n nn reports on this day, where 1 11 means entering school and 0 00 means leaving school. This report is considered correct if and only if there are no two consecutive reports of the same type. Now please judge whether this report is wrong.

answer:

According to the meaning of the question, it is enough to directly judge whether adjacent elements are equal

Code:

#include<bits/stdc++.h>	

#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair

using namespace std;

const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;

int t,n;
int a[maxn];
int main(){
    
    
	//freopen("in.txt", "r", stdin);//提交的时候要注释掉
	IOS;
	while(cin>>t){
    
    
		while(t--){
    
    
			cin>>n;
			rep(i,0,n-1){
    
    
				cin>>a[i];
			}
			bool flag=false;
			rep(i,0,n-2){
    
    
				if(a[i]==a[i+1]){
    
    
					flag=true;
					break;
				}
			}
			if(flag)
				cout<<"NO"<<endl;
			else
				cout<<"YES"<<endl;
		}
	}
	return 0;
}

Put apple

Title:

Put M identical apples on N identical plates, and allow some plates to be left empty. How many different divisions are there? (Represented by K) 5,1,1 and 1,5,1 are the same division.

answer:

: First, suppose that the total number of placing i apples on k plates is f(i,k). There are two cases for classification discussion
(1) When k> i, f (i, k) = f (i , i)
(2) When k <= i, the total placement method = the placement method with empty plates + the placement method with no plates empty
f (i, k) = f (i, k-1) + f ( i-k, k)

Code:

#include<iostream>
using namespace std;
//设 i个苹果放在 k个盘子里的放法总数是 f(i,k) 
int f(int i,int k){
    
    
    if(k > i){
    
    //当 k > i时,f(i,k) = f(i,i) 
        return f(i,i);
    }
    if(i == 0)
        return 1;
    if(k == 0){
    
    
        return 0;
    }
    //k <= i时,总放法 = 有盘子为空的放法+没盘子为空的放法
    //f(i,k) = f(i,k-1) + f(i-k,k) 
    return f(i,k-1)+f(i-k,k);
}

int main(){
    
    
    int t,i,k,count=0;
    cin>>t;
    while(t--){
    
    
        cin>>i>>k; 
        cout<<f(i,k)<<endl;
    }
    return 0;
} 

Monthly Expense

Title:

Given the farmer’s daily expenditure in n days, it is required to divide these n days into m groups, the number of days in each group must be continuous, and the sum of the costs of each group should be as small as possible, and finally output the costs of each group The maximum value of the sum

answer:

The maximum value of the minimum sum of each group should be divided into two, enumerate an answer, then verify whether it is reasonable, and continue to narrow the scope to determine the answer

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 100001
#define MOD 123
#define E 1e-6
using namespace std;
int n,m;
int a[N];
bool judge(int value)//判断当前花费可把n分成几组
{
    
    
    int sum=0;//花费总和
    int cnt=1;//初始时只有一组
    for(int i=0;i<n;i++)//枚举每天花费
    {
    
    
        if(sum+a[i]<=value)
            sum+=a[i];
        else
        {
    
    
            sum=a[i];
            cnt++;
        }
    }
    if(cnt>m)//若分组数比规定数要多,则mid偏小,需调整左值
        return false;
    else//若分组数比规定数要少,则mid偏大,需调整右值
        return true;
}
int main()
{
    
    
    while(scanf("%d%d",&n,&m)!=EOF)
    {
    
    
        int left=0,right=0;
        for(int i=0;i<n;i++)
        {
    
    
            scanf("%d",&a[i]);
            left=max(left,a[i]);
            right+=a[i];
        }
        int mid;
        while(left<=right)
        {
    
    
            mid=(left+right)/2;
            if(judge(mid))
                right=mid-1;
            else
                left=mid+1;
        }
        printf("%d\n",mid);
    }
    return 0;
 }

String Typing

Title:

For a string, you can copy a certain paragraph of characters, and ask how many steps are required to output it. For example, abcabcd, first input abc, then assign abc and then input d, it only takes 5 steps.
The copied character must be copied from position 0 of the string and can only be pasted once. Example abcabcabc output is 7

answer:

str.substr(i,j) in string Intercept a section of characters of length j
from the i-th position of the string str. Intercept a section of length i from the beginning to see if there is any overlap with the following

Code:

#include <bits/stdc++.h>
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 10010, INF = 0x7fffffff;

int main()
{
    
    
    int n;
    string str;
    cin>> n >> str;
    int res = n;
    for(int i=1; i<=n/2; i++)
        if(str.substr(0, i) == str.substr(i, i)) res = n - i + 1;
    cout<< res <<endl;

    return 0;
}

Diagonal Walking

Title:

Given n operations, the connected U and R can be seen as one step. Ask how many steps are there in total

answer:

You can simulate directly according to the question, skip when you encounter UR or RU, and calculate the number of steps for others

Code:

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int main(){
    
    
	int n;
	cin >> n;
	string s;
	cin >> s;
	int u = 0, r = 0, ans = 0;
	int len = s.size();
	for(int i = 0; i < s.size(); i++){
    
    
		if((s[i] == 'U' && s[i+1] == 'R') || (s[i] == 'R' && s[i+1] == 'U')){
    
    
			i++;  // 相连的U和R看为一步
		}
		ans++;
	}
	cout << ans << endl;
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_35975367/article/details/114115004