Notes on problem brushing of PTA ladder practice competition (L2 001-004) (under update)

Posted by QWERTYtech on Fri, 04 Mar 2022 12:11:00 +0100

Topic bank link: Group programming ladder competition - practice set

OP

\

L2-001 emergency rescue (25 points)

dijkstra algorithm
The boss said that SPFA can also be done. mark it and learn next

thinking

Can refer to here To understand the basic principle of dijestra;

The main characteristic of this problem is that the shortest path may have multiple planning routes, and there is only one optimal solution, that is, it needs to deal with the information of distance and number of people at the same time;

The main idea is to divide all points into two sets: reached points and missed points (01 marked with an array in the code). At the beginning, the reached points set has only the starting point, and the missed points set contains all the other points;

The main process is to traverse all the missed points in each cycle. For each missed point pj, if it can be connected to the reached point pi through a road (length ki), record the shortest distance from the missed point to the initial point (set the shortest distance from pi point to the starting point li, l j = m i n ( l i + k i ) l_j=min(l_i+k_i) lj = min(li + ki)), and record all i that can make lj take the minimum value as the number of schemes to reach this point;

Select the point with the shortest distance from the initial point among all the missed points, add it to the set of reached points, and select the point with the largest number of accumulated people as the point finally connected with it in all feasible schemes (i). The accumulated number of new points is the sum of the accumulated number of connected points and the original number of new points;

Cycle until the target is reached;

Finally, find out the points on the whole path in order and output them.

Code comments added
The part for storing the number of people can be optimized, that is, the smp variable is unnecessary
Time complexity O(n3)

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll M=1e9+7;
struct 
{
	vector<int>fr;//Store the point upstream, i.e. from i
	int strd=100000000;//Store the distance from the initial point, which is infinite by default
	int p=0;//Number of people storing this point
	int smp=0;//Stores the cumulative number of people from the initial point to this point
}cty[502];

int main()
{
	int n,m,f,t,a,b,l;//n is the number of cities, m is the road book, and abl is the variable for receiving roads
	int r[502][502]={0},rch[502]={0};//r is the road, which stores the road. If the length is 0, there is no road. It can be optimized here
									//The rch array stores the number of reached points and schemes, and 0 is not reached
	cin>>n>>m>>f>>t;
	cty[f].fr.push_back(f);//Initialization processing start point
	rch[f]=1;
	cty[f].strd=0;
	for(int i=0;i<n;i++)
	{
		cin>>cty[i].p;
		cty[i].smp=cty[i].p;
	}//Number of people receiving urban rescue
	for(int i=0;i<m;i++)//Receiving channel, symmetrically added to storage
	{
		cin>>a>>b>>l;
		if(r[a][b])r[a][b]=min(r[a][b],l);
		else r[a][b]=l;
		if(r[b][a])r[b][a]=min(r[b][a],l);
		else r[b][a]=l;
	}
	while(!rch[t])//If the target point is not reached, continue the cycle
	{
		int mnr=100000000-8,mnm=-1;//mnr stores the minimum distance between the missed point and the initial point
									//mnm stores the number of points satisfying mnr
		for(int i=0;i<n;i++)
		{
			if(!rch[i])//If not
			{
				cty[i].fr.clear();//initialization
				cty[i].strd=100000000;
				for(int j=0;j<n;j++)
				{
					if(rch[j]&&r[i][j])//Traverse every road leading to the reachable point
					{
						if(cty[j].strd+r[i][j]<cty[i].strd)//Smaller value
						{
							cty[i].strd=cty[j].strd+r[i][j];//Update minimum
							cty[i].fr.clear();//Situation scheme
							cty[i].fr.push_back(j);//j join the programme
						}
						else if(cty[j].strd+r[i][j]==cty[i].strd)//A value equal to the minimum
						{
							cty[i].fr.push_back(j);//j join the programme
						}
					}
				}
				if(cty[i].strd<mnr)//Update the minimum distance of this cycle
				{
					mnr=cty[i].strd;
					mnm=i;
				}
			}
		}
		int mxp=0,mxm=-1;//mxp records the maximum number of people accumulated, and mxm records the city number corresponding to mxp
		for(int j:cty[mnm].fr)
		{
			rch[mnm]+=rch[j];//The number of final schemes reaching new points is the sum of the number of point schemes corresponding to each feasible scheme
			if(cty[j].smp>mxp)//to update
			{
				mxp=cty[j].smp;
				mxm=j;
			}
		}
		cty[mnm].fr.clear();//Empty scheme
		cty[mnm].fr.push_back(mxm);//The scheme with the largest number of people will be determined as the final scheme
		cty[mnm].smp+=cty[mxm].smp;//Update accumulated number
		//printf("%d %d\n",mnm,rch[mnm]);
	}
	printf("%d %d\n",rch[t],cty[t].smp);//Number of output schemes and number of optimal schemes
	stack<int>stk;//Stack storage path node
	int now=t;
	stk.push(t);
	stk.push(cty[now].fr[0]);
	now=cty[now].fr[0];
	//printf("*%d",stk.top());
	while(stk.top()!=f)
	{
		stk.push(cty[now].fr[0]);
		now=cty[now].fr[0];
		//printf("*%d",stk.top());
	}
	printf("%d",stk.top());//Output start
	stk.pop();
	while(stk.size())
	{
		printf(" %d",stk.top());
		stk.pop();
	}
    return 0;
}

L2-002 linked list weight removal (25 points)

data structure

thinking

Save the previous node and update it as required;

Hold the starting point of the two linked lists;

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll M=1e9+7;
struct 
{
	int num;
	int nxt;
}vtr[100005];

int main()
{
	int f1,n,g,f2=-1;
	cin>>f1>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>g;
		cin>>vtr[g].num>>vtr[g].nxt;
	}//End of reception
	int now=f1,a[10004]={0},lst=0,now2;//a is used to remove the weight of the bucket. Now is the node being processed, lst is the previous node, and now2 is the end of another linked list
	while(now!=-1)//If the end of f1 is not reached, the loop continues
	{
		if(a[abs(vtr[now].num)])
		{
			vtr[lst].nxt=vtr[now].nxt;
			if(f2==-1)f2=now,now2=now,now=vtr[now].nxt,vtr[now2].nxt=-1;//If another linked list is not established
			else
			{
				vtr[now2].nxt=now;
				now2=now;
				now=vtr[now].nxt;
				vtr[now2].nxt=-1;
			}
			
		}
		else
		{
			a[abs(vtr[now].num)]=1;
			lst=now;
			now=vtr[now].nxt;
		}
	}
	now=f1;
	while(now!=-1)
	{
		printf("%05d %d ",now,vtr[now].num);
        if(vtr[now].nxt==-1)printf("%d\n",-1);
        else printf("%05d\n",vtr[now].nxt);//Note that the number of digits is required to be reserved
		now=vtr[now].nxt;
	}
	now=f2;
	while(now!=-1)
	{
		printf("%05d %d ",now,vtr[now].num);
        if(vtr[now].nxt==-1)printf("%d\n",-1);
        else printf("%05d\n",vtr[now].nxt);
		now=vtr[now].nxt;
	}
    return 0;
}

L2-003 moon cake (25 points)

Simulation, greed

thinking

Simulation is enough. Priority is given to those with high unit price;

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll M=1e9+7;
struct mooncake
{
	double w;
	double m;
}mnk[1003];

bool cmp(const mooncake a,const mooncake b)
{
	return 1.0*a.m/a.w>1.0*b.m/b.w;
}
//money per weight is sorted in descending order by unit price
int main()
{
	int t;
    double n;
	cin>>t>>n;
	for(int i=1;i<=t;i++)cin>>mnk[i].w;
	for(int i=1;i<=t;i++)cin>>mnk[i].m;
	sort(mnk+1,mnk+t+1,cmp);
	double s=0;
	for(int i=1;i<=t&&n;i++)
	{
		if(n>=mnk[i].w)
		{
			n-=mnk[i].w;
			s+=mnk[i].m;
		}
		else
		{
			s+=1.0*n*mnk[i].m/mnk[i].w;
			n=0;
		}
	}
	printf("%.2lf",s);
    return 0;
}

L2-004 is this a binary search tree? (25 points)

Preorder traversal of tree

thinking

For the binary search tree described in the title, the following properties are satisfied:
For a tree preorder traversal [l, R], the first element must be the root node;
Let's start from the second node, and the number of the first node greater than or equal to the root node is mk, m a x [ l , m k − 1 ] < r o o t , m i n [ m k , r ] < = r o o t max [ l , mk - 1 ]<root,min[ mk , r ]<=root max[l,mk−1]<root,min[mk,r]<=root;

Image tree is similar;

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll M=1e9+7;
queue<int>que;
int a[1003];
bool ju(int l,int r,int dir)//dir=1 is the forward tree, and dir=0 is the mirror tree
{
	int i,root=a[l],ans=1,mk=r+1,mi=root,mx=root-1;
	//Root stores the value of the root node of the subtree, and mk is the root node of the right subtree
	//mi is the minimum value of the target subtree and mx is the maximum value of the target word number
	/*if(l==r)			//Fool proof code, actually not used
	{
		que.push(a[l]);
		return 1;
	}
	else if(l>r)
	{
		return 1;
	}*/
	if(dir)
	{
		for(i=l+1;i<=r;i++)
		{
			if(a[i]>=root)mk=min(mk,i);
			if(mk==r+1)mx=max(mx,a[i]);//mk==r+1 indicates that this is still a left subtree
			else mi=min(mi,a[i]);
		}
		if(mk!=l+1&&mx>=root||mk!=r+1&&mi<root)//The criterion of mk can be deleted
		{
			//printf("%d %d %d %d %d\n",l,r,mi,mx,mk);
			return 0;
		}
	}
	else
	{
		for(i=l+1;i<=r;i++)
		{
			if(a[i]<root)mk=min(mk,i);
			if(mk==r+1)mi=min(mi,a[i]);
			else mx=max(mx,a[i]);
		}
		if(mk!=r+1&&mx>=root||mk!=l+1&&mi<root)
		{
			//printf("%d %d %d %d %d\n",l,r,mi,mx,mk);
			return 0;
		}
	}
	if(mk!=l+1)//If the left subtree exists
	{
		ans*=ju(l+1,mk-1,dir);
	}
	if(mk!=r+1)//If right subtree exists
	{
		ans*=ju(mk,r,dir);
	}
	que.push(root);//When the root node is put into the stack, it is the post order traversal
	return ans;
}
int main()
{
	int n,i,f=1;
	cin>>n;
	for(i=1;i<=n&&f;i++)cin>>a[i];
	{
		if(a[1]>a[2])f=ju(1,n,1);//Forward tree
		else f=ju(1,n,0);//Mirror tree
		if(f)
		{
			printf("YES\n",que.size());
			while(!que.empty())
			{
				printf("%d",que.front());
				if(que.size()!=1)printf(" ");
				que.pop();
			}
		}
		else printf("NO");
	}
    return 0;
}