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.