2020 Mathematical Model National Competition Question B 1st Question

Although it took so long to post...I am also curious whether my algorithm is correct emm

Let me talk about the result first: 10800... (It seems that I haven't seen a same emm... If you find a bug in my method, you can tell me Orz in the comment section

Algorithm idea: consider dp [i] [u] [x 1] [x 2] dp[i][u][x1][x2]d p [ i ] [ u ] [ x 1 ] [ x 2 ] is the i-th day, at node u, x1 units of water, x2 units of food, and the most money left

The transfer part is detailed in the code:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1000005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

inline int read()
{
    
    
	int x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {
    
    if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {
    
    x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}

int a[maxn]={
    
    0,2,2,1,3,1,2,3,1,2,2,
			   3,2,1,2,2,2,3,3,2,2,
			   1,1,2,1,3,2,1,1,2,2};

vector <int> mp[maxn];
int n,m,d[55][55],dp[35][35][305][305];

inline int X(int x)
{
    
    
	if(x==1) return 5;
	else if(x==2) return 8;
	else return 10;
}

inline int Y(int y)
{
    
    
	if(y==1) return 7;
	else if(y==2) return 6;
	else return 10;
}

int main()
{
    
    
	//freopen("t2.in","r",stdin);
	//freopen("t1.out","w",stdout);
	n=read(),m=read();
	rep(i,1,n) rep(j,1,n) d[i][j]=inf; rep(i,1,n) d[i][i]=0;
	rep(i,1,m)
	{
    
    
		int u=read(),v=read();
		d[u][v]=1; d[v][u]=1;
		mp[u].pb(v); mp[v].pb(u);
	}
	rep(k,1,n) rep(i,1,n) rep(j,1,n) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
	
	rep(i,0,30) rep(j,1,30) rep(k,0,300) rep(w,0,300) dp[i][j][k][w]=-inf;
	
	int s=1,t=27;
	
	rep(i,0,300) rep(j,0,300)
	{
    
    
		int x=3*i+2*j; if(x>1200) continue;
		int y=5*i+10*j; if(y>10000) continue;
		dp[0][s][i][j]=10000-y;
	}
	
	for(int i=1;i<=30;i++)
	{
    
    
		for(int u=1;u<=n;u++)
		{
    
    
			rep(j,0,300) rep(k,0,300)
			{
    
    
				if(dp[i-1][u][j][k]==-inf) continue;
				
				int tx=X(a[i]),ty=Y(a[i]);
				
				//stay for a day
				if(j>=tx&&k>=ty)
					dp[i][u][j-tx][k-ty]=max(dp[i][u][j-tx][k-ty],dp[i-1][u][j][k]);
					
				//buy
				if(u==15)
				{
    
    
					rep(j1,0,300)
					{
    
    
						rep(k1,0,300)
						{
    
    
							int x=3*j1+2*k1; if(x+j1*3+k1*2>1200) break;
							int y=10*j1+20*k1; if(y>dp[i][u][j][k]) break;
							if(j+j1>300|k+k1>300) break;
							dp[i][u][j+j1][k+k1]=max(dp[i][u][j+j1][k+k1],dp[i-1][u][j][k]-y);
						}
					}
				}
				
				//dig
				if(u==12&&j>=3*tx&&k>=3*ty)
					dp[i][u][j-3*tx][k-3*ty]=max(dp[i][u][j-3*tx][k-3*ty],dp[i-1][u][j][k]+1000);
					
				//move to adjacent
				if(a[i]!=3)
				{
    
    
					for(int z=0;z<mp[u].size();z++)
					{
    
    
						int v=mp[u][z];
						if(j>=2*tx&&k>=2*ty)
							dp[i][v][j-2*tx][k-2*ty]=max(dp[i][v][j-2*tx][k-2*ty],dp[i-1][u][j][k]);
					}
				}
			}
		}
	}
	
	//cout<<dp[28][27][0][0]<<endl;
	
	int ans=-inf,ni=0,nj=0,nk=0,nu=t;
	rep(i,1,30) rep(j,0,300) rep(k,0,300)
	{
    
    
		if(dp[i][t][j][k]+5*j+10*k>ans)
			ans=dp[i][t][j][k]+5*j+10*k,ni=i,nj=j,nk=k;
	}
	
	cout<<ans<<endl;
	
	/*while(1)
	{
		int a=read(),b=read(),c=read(),d=read();
		printf("%d\n",dp[a][b][c][d]);
	}
	*/
	
	return 0;
}

Personally feel very rigorous? The complexity is relatively high, and it may take about 3 minutes to get the answer. You can wait patiently for the meeting. If you find something wrong in the code, you can leave a message emm

The following is the data of t2.in in the code, you can run:

27 51
1 2
1 25
2 3
3 4
3 25
4 5
4 24
4 25
5 6
6 7
6 23
6 24
7 8
7 22
8 9
8 22
9 10
9 15
9 16
9 17
9 21
9 22
10 11
10 13
10 15
11 12
11 13
12 13
12 14
13 14
13 15
14 15
14 16
16 17
16 18
17 18
17 21
18 19
18 20
19 20
20 21
21 22
21 23
21 27
22 23
23 24
23 26
24 25
24 26
25 26
26 27

The second level can also be solved by applying this code, just change part of the data, but because of laziness + teammates are useless... so I just coo.

As for the output scheme, you can play it by hand/write another dp and deal with it backwards.

The reason is the same as above.

Guess you like

Origin blog.csdn.net/qq_38649940/article/details/108605910