"Meituan CodeM Preliminary Round B" Delivery 2

Topic description:

On a graph with n points and m directed edges, there are q delivery requirements, and the description of the requirements is (si, ti, li, ri), that is, it needs to be sent from point si to ti, and after time li (including li) The goods can be picked up at si and need to be delivered to ti before (including ri) time ri, and each task only needs to be completed once. Each edge on the graph has an edge weight, and the weight represents the time spent passing through this edge. At time 0, there is a worker at point 1, asking him how many delivery tasks he can complete at most. In the whole process, it can be considered that picking up and delivering goods does not consume time, and time is only spent on the journey. Of course staying at one point is also allowed.

data range:

2n20

1m400

1q10

---------- ---------- ---------- ---------- ---------- I am the gorgeous dividing line ---------- ---------- ---------- ---------- ---- ------

answer:

This is a state compression DPfloodquestion.

It should be noted that the given edges are all directed edges, and the delivery boy is allowed to carry multiple goods at the same time.

Observing the data range, it is found that the data is very small. Consider the violent enumeration and distribution order, and then simulate it, but obviously TLE...

So...

Considering that each task has only 3 possible states (not picked up, picked up but not delivered, and delivered), a 3-ary state pressure DP can be written. However, since the 3-system is a little troublesome to use, and the space complexity can be tolerated, it is considered to use 2 binary numbers to represent the state. Therefore, F[i][j][k] is defined to indicate the minimum time required for the current state, i indicates the number of the current node, j and k are binary numbers, respectively indicating the goods currently carried on the body and undelivered goods.

Next consider state transitions.

For the current F[i][j][k], enumerate the next unfinished task ta. If the task has been carried on the body, then judge whether it is better to transfer from the current state (of course, the main premise is that it is too late to go immediately), and if it is better, update the next state. If the task has not been carried on the body, then go to pick up the goods, and also need to judge whether it is better to transfer from the current state.

Then you can start happy DFS.

Considering the original definition of DP, it is not difficult to find that the answer is the maximum number of completed tasks in all possible states (that is, the states that have been brushed).

Finally, paste the C++ code:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,q,ans,F[21][1025][1025],dist[21][21],s[11],t[11],l[11],r[11];
void Update(int k)
{
	int tot = 0;
	for (int ta = 1; ta <= q; ta ++)
		if(!(k&(1<<ta-1)))
			to++;
	if(tot>ans) ans=tot;
}
void DFS(int i,int j,int k)
{
	Update(k);//Update the answer
	for (int ta = 1; ta <= q; ta ++)
	{
		if(k&(1<<ta-1))//The ta-th task is not dispatched
		{
			if(j&(1<<ta-1))//The ta th task has been brought on the body, and the task is delivered
			{
				if(F[i][j][k]+dist[i][t[ta]]<F[t[ta]][j-(1<<ta-1)][k-(1<<ta-1)]&&F[i][j][k]+dist[i][t[ta]]<=r[ta])
				{
					F [t [ta]] [j- (1 << ta-1)] [k- (1 << ta-1)] = F [i] [j] [k] + dist] i] [t [ ta]];
					DFS(t[ta],j-(1<<ta-1),k-(1<<ta-1));
				}
			}
			else//There is no ta task on you, go and get the task
			{
				if(max(F[i][j][k]+dist[i][s[ta]],l[ta])<F[s[ta]][j+(1<<ta-1)][k])
				{
					F [s [ta]] j + (1 << ta-1)] [k] = max (F [i] [j] [k] + dist] i] [s [ta]], );
					DFS(s[ta],j+(1<<ta-1),k);
				}
			}
		}
	}
}
intmain()
{
	scanf("%d%d%d",&n,&m,&q);
	memset(dist,63,sizeof(dist));memset(F,63,sizeof(F));
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		if(dist[a][b]>c) dist[a][b]=c;
	}
	for(int i=1;i<=q;i++)
		scanf("%d%d%d%d",&s[i],&t[i],&l[i],&r[i]);
	for(int k=1;k<=n;k++) //Floyd brushes out the shortest path between each two points
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				if(dist[i][k]+dist[k][j]<dist[i][j])
					dist[i][j]=dist[i][k]+dist[k][j];
	for(int i=1;i<=n;i++) dist[i][i]=0;
	F[1][0][(1<<q)-1]=0;
	DFS(1,0,(1<<q)-1);
	printf("%d\n",ans);
	return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324654420&siteId=291194637