Mathematical modeling 2020B questions across the desert

1. Topic

Consider the following small game: With a map, the player uses the initial funds to purchase a certain amount of water and food (including food and other daily necessities), and starts from the starting point to walk in the desert. You will encounter different weather on the way, and you can also replenish funds or resources in mines and villages. The goal is to reach the end within the specified time and retain as much funds as possible.
The basic rules of the game are as follows:
(1) Taking days as the basic time unit, the game starts at day 0, and the player is at the starting point. A player must reach the finish line on or before the deadline, after which the player's game ends.
(2) Two resources, water and food, are needed to cross the desert, and their smallest unit of measurement is a box. The sum of the quality of water and food owned by the player every day cannot exceed the weight limit. If the finish point is not reached and the water or food is exhausted, the game is considered a failure.
(3) The daily weather is one of the three conditions of "clear", "high temperature" and "sandstorm", and the weather in all areas in the desert is the same.
(4) Players can go from one area in the map to another adjacent area every day, or stay in place. Sandstorm days must stay put.
(5) The amount of resources consumed by the player staying in place for one day is called the basic consumption, and the amount of resources consumed by walking for one day is the times of the basic consumption.
(6) On the 0th day, players can use the initial funds to purchase water and food at the base price at the starting point. Players can stay at the starting point or return to the starting point, but they cannot buy resources at the starting point multiple times. Players can return the remaining water and food after reaching the end point, and the return price of each box is half of the base price.
(7) When players stay in the mine, they can obtain funds through mining. The amount of funds obtained by mining for one day is called the basic income. If mining, the amount of resources consumed is the times of the base consumption; if not mining, the amount of resources consumed is the base consumption. You cannot mine on the day you arrive at the mine. Mining is also available on sandstorm days.
(8) Players can use the remaining initial funds or funds obtained from mining to purchase water and food at any time when they pass by or stay in the village, and the price of each box is twice the base price.
Please build a mathematical model according to the different settings of the game to solve the following problems.

  1. Assuming that there is only one player and the weather conditions are known in advance every day during the entire game period, try to give the player's optimal strategy under normal circumstances. Solve the "First Level" and "Second Level" in the attachment, and fill the corresponding results into Result.xlsx respectively.
  2. Assuming there is only one player, and the player only knows the weather conditions of the day, he can decide the action plan for the day accordingly, try to give the best strategy for the player under normal circumstances, and analyze the "third level" and "fourth level" in the attachment. " for detailed discussion.

2. Problem-solving ideas and the first and second levels

There are three kinds of ideas
1. Dynamic programming
2. Use the Dijkstra algorithm to solve after a brief map
3. Analyze the problem and then build a model Use groubi and lingo to find the optimal solution

2.1 Dynamic programming situation

Assuming that the state dp[k][j][w][f] represents the remaining water at the jth point on the k-th day is the maximum fund of the w box and the remaining food is the f box, then:

ans=MAXw,f,i dp[k][zd][w][f]

2.1.1 Initial value setting

Since the starting point can purchase materials at the starting point, there is an initial state
dp[0][qd][w][f]=10000−cost_water∗w−cost_food∗fw∈[0,400]f∈[0,600]
where cost_water​​, cost_food​​​​ The money spent to buy water and food.
Here it is assumed that the start is day 0, and the weather on the first day affects from day 0 to day 1.

2.1.2 State transition equation

When the person is in village j on the kth day:

  1. The kth day is a sandstorm
dp[k+1][j][w+ww-xh_water[tq]][f+ff-xh_food[tq]]}=max(dp[k][j][w][f]-2*ww*cost_water-2*ff*cost_food
  1. Non-sandstorm weather:
dp[k+1][jj][w+ww-xh_water[tq]][f+ff-xh_food[tq]]}=max(dp[k][j][w][f]-2*ww*cost_water-2*ff*cost_food

When the person is in mine j on day k:
mining

dp[k+1][j][w-dig*xh_water[tq]][f-dig*xh_food[tq]]=max(dp[k][j][w][f]+1000)

Day k is sandstorm weather:

dp[k+1][j][w-xh_water[tq]][f-xh_food[tq]]=max(dp[k][j][w][f])

Day k is non-sandstorm weather:

dp[k+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]=max(dp[k][jj][w][f])

When the person on the k-th day is in another area,
the k-th day is sandstorm weather:

dp[k+1][j][w-xh_water[tq]][f-xh_food[tq]]=max(dp[k][j][w][f])

Day k is non-sandstorm weather:

dp[k][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]=max(dp[k][j][w][f])

2.1.3 Thinking about implicit condition constraint model

In addition to returning to the village to replenish supplies, there will be no turning back.
Except mining and sandstorms will not stay in place.
Only the shortest path between key points will be taken

2.1.4 Code

first round

#include<bits/stdc++.h>
#include<iostream>
using namespace std;

// 点数
const int N=11,M=28,inf=0x3f3f3f,Day=30;
int dp[32][N+1][405][605],zd,qd,FZ;
int cost_water,cost_food,walk,dig,buy;
int xh_water[3]={
    
    5,8,10},xh_food[3]={
    
    7,6,10};
bool cz[N+1],ks[N+1];

struct node
{
    
    
    short day; // i 
    short from; // jj j
    int water,food;
    int money;
    bool operator!=(const node &x){
    
    
        return x.day!=day || x.from!=from || x.water!=water || x.food!=food ;
    };
}path[31][N+1][405][605],lastpath;
vector <int> weather;
vector <int> g[N];
map <int,int> mp;
void push_back(int x,int y)
{
    
    
    g[x].push_back(y);
    g[y].push_back(x);
}

void build_map()
{
    
    
    push_back(1,2);
    push_back(2,3);
    push_back(2,5);
    push_back(5,6);
    push_back(3,4);
    push_back(4,7);
    push_back(6,7);
    push_back(7,8);
    push_back(8,9);
    push_back(9,10);
    push_back(10,11);

    mp[1]=1;
    mp[2]=25;
    mp[3]=26;
    mp[4]=27;
    mp[5]=24;
    mp[6]=23;
    mp[7]=21;
    mp[8]=9;
    mp[9]=15;
    mp[10]=14;
    mp[11]=12;
	for(int i=1;i<=N;i++)
    {
    
    
        cz[i]=0;
        ks[i]=0;
    }
    cz[9]=1;
    ks[11]=1;
	zd=4;
    qd=1;
    
    return ;
}
void init()
{
    
    
    memset(dp,-inf,sizeof(dp));
    FZ=1200;
    cost_water=5;
    cost_food=10;

    walk=2;
    buy=2;
    dig=3;

    
    for(int k=0;k<=405;k++)
    {
    
    
        for(int l=0;l<=601;l++)
        {
    
    
            if(k*3+l*2<=FZ)
            {
    
    
                dp[0][qd][k][l]=10000-k*cost_water-l*cost_food;
            }
        }
    }
    printf("init %d\n",dp[0][1][178][333]);
    path[0][1][0][0]={
    
    0,0,0,0};
    return ;
}
int main()
{
    
    
    
    weather={
    
    
        1,1,0,2,0,1,2,0,1,1,
        2,1,0,1,1,1,2,2,1,1,
        0,0,1,0,2,1,0,0,1,1,
    };
    
    build_map();
    init();
    for(int i=0;i<Day;i++)
    {
    
    
        printf("第%d天\n",i);
        int tq=weather[i];
        for(int j=1;j<=N;j++)
        {
    
    
            if(cz[j])// 村庄
            {
    
    
                for(int w=0;w<=405;w++)
                {
    
    
                    for(int f=0;w*3+f*2<=1200;f++)
                    {
    
    
                        //购买或不够买物资(ww=0,ff=0就是不购买) 
                        if(tq==2) //停留
                        {
    
    
	                        int money=dp[i][j][w][f];
	                        for(int ww=0;ww<=money/cost_water;ww++)
	                        {
    
    
	                            for(int ff=0;ff<=(FZ-(w+ww)*3)/2-f;ff++)
	                            {
    
    
                                
                                    if(w+ww-xh_water[tq]>=0&&f+ff-xh_food[tq]>=0&&dp[i][j][w][f]-2*ww*cost_water-2*ff*cost_food>=0)
                                    {
    
    
                                        if(dp[i+1][j][w+ww-xh_water[tq]][f+ff-xh_food[tq]]<dp[i][j][w][f]-2*ww*cost_water-2*ff*cost_food)
                                        {
    
    
                                            dp[i+1][j][w+ww-xh_water[tq]][f+ff-xh_food[tq]]=dp[i][j][w][f]-2*ww*cost_water-2*ff*cost_food;
                                            path[i+1][j][w+ww-xh_water[tq]][f+ff-xh_food[tq]]={
    
    i,j,w,f,dp[i][j][w][f]-2*ww*cost_water-2*ff*cost_food};
                                        }
                                    }

                                }
                            }
                        }
                        else //从j走到jj
                        {
    
    
                            for(auto jj:g[j])
                            {
    
    
                            	int money=dp[i][j][w][f];
		                        for(int ww=0;ww<=money/cost_water;ww++)
		                        {
    
    
		                            for(int ff=0;ff<=(FZ-(w+ww)*3)/2-f;ff++)
		                            {
    
    
		                                if(w+ww-walk*xh_water[tq]>=0&&f+ff-walk*xh_food[tq]>=0&&dp[i][j][w][f]-buy*ww*cost_water-buy*ff*cost_food>=0)
		                                {
    
    
		                                    if(dp[i+1][jj][w+ww-walk*xh_water[tq]][f+ff-walk*xh_food[tq]]<dp[i][j][w][f]-buy*ww*cost_water-buy*ff*cost_food)
		                                    {
    
    
		                                        dp[i+1][jj][w+ww-walk*xh_water[tq]][f+ff-walk*xh_food[tq]]=dp[i][j][w][f]-buy*ww*cost_water-buy*ff*cost_food;
		                                        path[i+1][jj][w+ww-walk*xh_water[tq]][f+ff-walk*xh_food[tq]]={
    
    i,j,w,f,dp[i][j][w][f]-buy*ww*cost_water-buy*ff*cost_food};
		                                    }
		                                    
		                                }
		                            }
		                        }
                            }
                        }
                    }
                }
            }
            else if (ks[j])// 矿山
            {
    
    
                for(int w=0;w<=405;w++)
                {
    
    
                    for(int f=0;w*3+f*2<=1200;f++)
                    {
    
    
                        // 已经停留一天了,可以挖矿
                        if(w-dig*xh_water[tq]>=0&&f-dig*xh_food[tq]>=0)
                        {
    
    
                            if(dp[i+1][j][w-dig*xh_water[tq]][f-dig*xh_food[tq]]<dp[i][j][w][f]+1000&&dp[i][j][w][f]>=0)
                            {
    
    
                                dp[i+1][j][w-dig*xh_water[tq]][f-dig*xh_food[tq]]=dp[i][j][w][f]+1000;
                                path[i+1][j][w-dig*xh_water[tq]][f-dig*xh_food[tq]]={
    
    i,j,w,f,dp[i][j][w][f]+1000};
                            }
                        
                        }
                        // 在矿山不挖矿或 不允许挖矿
                        if(tq==2) //停留但不挖矿
                        {
    
    
                            if(w-xh_water[tq]>=0&&f-xh_food[tq]>=0)
                            {
    
    
                                if(dp[i+1][j][w-xh_water[tq]][f-xh_food[tq]]<dp[i][j][w][f]&&dp[i][j][w][f]>=0)
                                {
    
    

                                    dp[i+1][j][w-xh_water[tq]][f-xh_food[tq]]=dp[i][j][w][f];
                                    path[i+1][j][w-xh_water[tq]][f-xh_food[tq]]={
    
    i,j,w,f,dp[i][j][w][f]};
                                }
                        
                            }
                        }
                        else
                        {
    
    
                            if(w-walk*xh_water[tq]>=0&&f-walk*xh_food[tq]>=0)
                            {
    
    
                                for(auto jj:g[j])
                                {
    
    
                                    if(dp[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]<dp[i][j][w][f]&&dp[i][j][w][f]>=0)
                                    {
    
    
                                        dp[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]=dp[i][j][w][f];
                                        path[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]={
    
    i,j,w,f,dp[i][j][w][f]};
                                    }
                                
                                }
                            }
                        }
                    }
                }
            }
            else //普通区
            {
    
    
                for(int w=0;w<=405;w++)
                {
    
    
                    for(int f=0;w*3+f*2<=1200;f++)
                    {
    
    
                        if(tq==2) //在j点停留
                        {
    
    
                            if(w-xh_water[tq]>=0&&f-xh_food[tq]>=0&&dp[i][j][w][f]>=0)
                            {
    
    
                                if(dp[i+1][j][w-xh_water[tq]][f-xh_food[tq]]<dp[i][j][w][f])
                                {
    
    
                                    dp[i+1][j][w-xh_water[tq]][f-xh_food[tq]]=dp[i][j][w][f];
                                    path[i+1][j][w-xh_water[tq]][f-xh_food[tq]]={
    
    i,j,w,f,dp[i][j][w][f]};
                                }
                            }
                        }
                        else// 走到jj点
                        {
    
    
                            for(auto jj:g[j])
                            {
    
    
                                if(w-walk*xh_water[tq]>=0&&f-walk*xh_food[tq]>=0&&dp[i][j][w][f]>=0)
                                {
    
    
                                    if(dp[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]<dp[i][j][w][f])
                                    {
    
    
                                        
                                        dp[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]=dp[i][j][w][f];
                                        path[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]={
    
    i,j,w,f,dp[i][j][w][f]};

                                    }
                                
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    int ans=-inf;
    node lastpath;
    int last_water=0,last_food=0,last_day=Day;
    for(int i=0;i<=Day;i++)
    {
    
    
        for(int w=0;w<=405;w++)
            for(int f=0;w*3+2*f<=1200;f++)
            {
    
    
                if(dp[i][zd][w][f]>ans)
                {
    
    
                    ans=dp[i][zd][w][f];
                    lastpath=path[i][zd][w][f];
                	last_water=w;
                	last_food=f;
                	last_day=i;
				}
            }
    }
    stack<node> s;
    stack<int> my;
    printf("??day:%d weather:%d %d water:%d food:%d money:%d\n",last_day,weather[Day],zd,last_water,last_food,ans);
    s.push((node){
    
    last_day,zd,last_water,last_food,ans});
    
    
	while(lastpath!=path[0][1][0][0])
    {
    
    
        s.push(lastpath);
        printf("??day:%d weather:%d %d water:%d food:%d money:%d\n",lastpath.day,weather[lastpath.day],mp[lastpath.from],lastpath.water,lastpath.food,lastpath.money);
		my.push(lastpath.money);
        lastpath=path[lastpath.day][lastpath.from][lastpath.water][lastpath.food];
    }
    freopen("output.txt","w",stdout);
    my.push(my.top());
    while (!s.empty())
    {
    
    
        node t=s.top();
        int money=my.top();
        printf("Day:%d weather:%d point:%d water:%d food:%d money:%d\n",t.day,weather[t.day],mp[t.from],t.water,t.food,money);
        s.pop();
        my.pop();
    }
    printf("%d\n",ans);
    return 0;
}

second level

#include<bits/stdc++.h>
#include<iostream>
using namespace std;

const short N=27,inf=20000,Day=30;
short dp[31][N+1][401][601],zd,qd,FZ;
short cost_water,cost_food,walk,dig,buy;
short xh_water[3]={
    
    5,8,10},xh_food[3]={
    
    7,6,10};
bool cz[N+1],ks[N+1];

struct node
{
    
    
    char day; // i 
    char from; // jj j
    short water,food;
    bool operator!=(const node &x){
    
    
        return (x.day-'0')!=(day-'0') || (x.from-'0'!=from-'0') || (x.water-'0')!=(water-'0') || (x.food-'0'!=food-'0') ;
    };
}path[31][N+1][401][601],lastpath;
vector <short> weather;
vector <short> g[N+1];
map <short,short> mp;
void push_back(short x,short y)
{
    
    
    g[x].push_back(y);
    g[y].push_back(x);
}

void build_map(short flag)
{
    
    
    if(flag==2)
    {
    
    
    	push_back(1,2);
        push_back(2,3);
        push_back(3,4);
        push_back(4,5);
        push_back(5,6);
        push_back(6,7);
        push_back(7,8);
        push_back(8,9);
        push_back(9,10);
        push_back(10,11);
        push_back(11,12);
        push_back(7,13);
        push_back(13,14);
        push_back(14,15);
        push_back(15,16);
        push_back(15,10);
        push_back(15,11);
        push_back(16,12);
        push_back(3,17);
        push_back(17,18);
        push_back(18,19);
        push_back(19,20);
        push_back(20,21);
        push_back(21,22);
        push_back(22,23);
        push_back(15,23);
        push_back(23,16);

        mp[1]=1;
        mp[2]=2;
        mp[3]=3;
        mp[4]=4;
        mp[5]=12;
        mp[6]=21;
        mp[7]=29;
        mp[8]=30;
        mp[9]=39;
        mp[10]=47;
        mp[11]=56;
        mp[12]=64;
        mp[13]=38;
        mp[14]=46;
        mp[15]=55;
        mp[16]=63;
        mp[17]=11;
        mp[18]=20;
        mp[19]=28;
        mp[20]=37;
        mp[21]=45;
        mp[22]=54;
        mp[23]=62;
        for(short i=1;i<=N;i++)
        {
    
    
            cz[i]=0;
            ks[i]=0;
        }
        cz[9]=cz[23]=1;
        ks[8]=ks[15]=1;
        qd=1;
        zd=12;
	}
    return ;
}

void init()
{
    
    
	
    FZ=1200;
    cost_water=5;
    cost_food=10;

    walk=2;
    buy=2;
    dig=3;
	for(short i=0;i<=Day;i++)
	{
    
    
		for(short j=1;j<=N;j++)
		{
    
    
			for(short w=0;w<=400;w++)
			{
    
    
				for(short f=0;f<=600;f++)
				{
    
    
					if(w*3+f*2<=FZ)
					{
    
    
						dp[i][j][w][f]=-inf;
					}
				}
			}
		}
	}
    for(short k=10;k<=405;k++)
    {
    
    
        for(short l=0;k*3+l*2<=FZ;l++)
        {
    
    
    		dp[0][qd][k][l]=10000-k*cost_water-l*cost_food;
        }
    }
    path[0][1][0][0]={
    
    0,0,0,0};
    return ;
}

int main()
{
    
    
    
    weather={
    
    
        1,1,0,2,0,1,2,0,1,1,
        2,1,0,1,1,1,2,2,1,1,
        0,0,1,0,2,1,0,0,1,1,
    };
    
    build_map(2);
    init();
    // dp [i][j][w][f]
    // 第i天 在j个点 w 箱水 f 箱食物 时最大利润,
    // max_k_l (dp[30][27][k][l])
    // 第i天的天气决定 i+1天能否移动
    // 如:第0天天气决定第1天能否移动

    // 先不考虑非矿山停留自愿停留情况
    // for(short i=1;i<N;i++)
    // {
    
    
    //     printf("第%d个点",i);
    //     for(auto j:mp[i]) 
    //     {
    
    
    //         printf("%d ",j);
    //     }
    //     printf("\n");
    // }
    // printf("???%d %d %d %d\n",xh_food[0],xh_food[2],xh_water[0],xh_water[1]);
    for(short i=0;i<Day;i++)
    {
    
    
        printf("第%d天\n",i);
        short tq=weather[i];
        for(short j=1;j<=N;j++)
        {
    
    
            if(cz[j])// 村庄
            {
    
    
                for(short w=0;w<=405;w++)
                {
    
    
                    for(short f=0;w*3+f*2<=1200;f++)
                    {
    
    
                        //购买或不够买物资(ww=0,ff=0就是不购买) 
                        if(tq==2) //停留
                        {
    
    
	                        short money=dp[i][j][w][f];
	                        for(short ww=0;ww<=money/cost_water;ww++)
	                        {
    
    
	                            for(short ff=0;ff<=(FZ-(w+ww)*3)/2-f;ff++)
	                            {
    
    
                                
                                    if(w+ww-xh_water[tq]>=0&&f+ff-xh_food[tq]>=0&&dp[i][j][w][f]-2*ww*cost_water-2*ff*cost_food>=0)
                                    {
    
    
                                        if(dp[i+1][j][w+ww-xh_water[tq]][f+ff-xh_food[tq]]<dp[i][j][w][f]-2*ww*cost_water-2*ff*cost_food)
                                        {
    
    
                                            dp[i+1][j][w+ww-xh_water[tq]][f+ff-xh_food[tq]]=dp[i][j][w][f]-2*ww*cost_water-2*ff*cost_food;
                                            // path[i+1][j][w+ww-xh_water[tq]][f+ff-xh_food[tq]]={i,j,w,f,dp[i][j][w][f]-2*ww*cost_water-2*ff*cost_food};
                                            path[i+1][j][w+ww-xh_water[tq]][f+ff-xh_food[tq]]={
    
    i,j,w,f};
                                        }
                                    }

                                }
                            }
                        }
                        else //从j走到jj
                        {
    
    
                            for(auto jj:g[j])
                            {
    
    
                            	short money=dp[i][j][w][f];
		                        for(short ww=0;ww<=money/cost_water;ww++)
		                        {
    
    
		                            for(short ff=0;ff<=(FZ-(w+ww)*3)/2-f;ff++)
		                            {
    
    
		                                if(w+ww-walk*xh_water[tq]>=0&&f+ff-walk*xh_food[tq]>=0&&dp[i][j][w][f]-buy*ww*cost_water-buy*ff*cost_food>=0)
		                                {
    
    
		                                    if(dp[i+1][jj][w+ww-walk*xh_water[tq]][f+ff-walk*xh_food[tq]]<dp[i][j][w][f]-buy*ww*cost_water-buy*ff*cost_food)
		                                    {
    
    
		                                        dp[i+1][jj][w+ww-walk*xh_water[tq]][f+ff-walk*xh_food[tq]]=dp[i][j][w][f]-buy*ww*cost_water-buy*ff*cost_food;
		                                        // path[i+1][jj][w+ww-walk*xh_water[tq]][f+ff-walk*xh_food[tq]]={i,j,w,f,(short)dp[i][j][w][f]-buy*ww*cost_water-buy*ff*cost_food};
		                                        path[i+1][jj][w+ww-walk*xh_water[tq]][f+ff-walk*xh_food[tq]]={
    
    i,j,w,f};
		                                    }
		                                    
		                                }
		                            }
		                        }
                            }
                        }
                    }
                }
            }
            else if (ks[j])// 矿山
            {
    
    
                for(short w=0;w<=405;w++)
                {
    
    
                    for(short f=0;w*3+f*2<=1200;f++)
                    {
    
    
                        // 已经停留一天了,可以挖矿
                        if(w-dig*xh_water[tq]>=0&&f-dig*xh_food[tq]>=0)
                        {
    
    
                            if(dp[i+1][j][w-dig*xh_water[tq]][f-dig*xh_food[tq]]<dp[i][j][w][f]+1000&&dp[i][j][w][f]>=0)
                            {
    
    
                                dp[i+1][j][w-dig*xh_water[tq]][f-dig*xh_food[tq]]=dp[i][j][w][f]+1000;
//                                path[i+1][j][w-dig*xh_water[tq]][f-dig*xh_food[tq]]={i,j,w,f,(short)dp[i][j][w][f]+1000};
                                path[i+1][j][w-dig*xh_water[tq]][f-dig*xh_food[tq]]={
    
    i,j,w,f};
                            }
                        
                        }
                        // 在矿山不挖矿或 不允许挖矿
                        if(tq==2) //停留但不挖矿
                        {
    
    
                            if(w-xh_water[tq]>=0&&f-xh_food[tq]>=0)
                            {
    
    
                                if(dp[i+1][j][w-xh_water[tq]][f-xh_food[tq]]<dp[i][j][w][f]&&dp[i][j][w][f]>=0)
                                {
    
    

                                    dp[i+1][j][w-xh_water[tq]][f-xh_food[tq]]=dp[i][j][w][f];
                                    // path[i+1][j][w-xh_water[tq]][f-xh_food[tq]]={i,j,w,f,dp[i][j][w][f]};
                                    path[i+1][j][w-xh_water[tq]][f-xh_food[tq]]={
    
    i,j,w,f};
                                }
                        
                            }
                        }
                        else
                        {
    
    
                            if(w-walk*xh_water[tq]>=0&&f-walk*xh_food[tq]>=0)
                            {
    
    
                                for(auto jj:g[j])
                                {
    
    
                                    if(dp[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]<dp[i][j][w][f]&&dp[i][j][w][f]>=0)
                                    {
    
    
                                        dp[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]=dp[i][j][w][f];
                                        // path[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]={i,j,w,f,dp[i][j][w][f]};
                                        path[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]={
    
    i,j,w,f};
                                    }
                                
                                }
                            }
                        }
                    }
                }
            }
            else //普通区
            {
    
    
                for(short w=0;w<=405;w++)
                {
    
    
                    for(short f=0;w*3+f*2<=1200;f++)
                    {
    
    
                        if(tq==2) //在j点停留
                        {
    
    
                            if(w-xh_water[tq]>=0&&f-xh_food[tq]>=0&&dp[i][j][w][f]>=0)
                            {
    
    
                                if(dp[i+1][j][w-xh_water[tq]][f-xh_food[tq]]<dp[i][j][w][f])
                                {
    
    
                                    dp[i+1][j][w-xh_water[tq]][f-xh_food[tq]]=dp[i][j][w][f];
                                    // path[i+1][j][w-xh_water[tq]][f-xh_food[tq]]={i,j,w,f,dp[i][j][w][f]};
                                    path[i+1][j][w-xh_water[tq]][f-xh_food[tq]]={
    
    i,j,w,f};
                                }
                            }
                        }
                        else// 走到jj点
                        {
    
    
                            for(auto jj:g[j])
                            {
    
    
                                if(w-walk*xh_water[tq]>=0&&f-walk*xh_food[tq]>=0&&dp[i][j][w][f]>=0)
                                {
    
    
                                    if(dp[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]<dp[i][j][w][f])
                                    {
    
    
                                        
                                        dp[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]=dp[i][j][w][f];
                                        // path[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]={i,j,w,f,dp[i][j][w][f]};
                                        path[i+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]={
    
    i,j,w,f};

                                    }
                                
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    short ans=-inf;
    node lastpath;
    short last_water=0,last_food=0,last_day=Day;
    for(short i=0;i<=Day;i++)
    {
    
    
        for(short w=0;w<=405;w++)
            for(short f=0;w*3+2*f<=1200;f++)
            {
    
    
                if(dp[i][zd][w][f]>ans)
                {
    
    
                    ans=dp[i][zd][w][f];
                    lastpath=path[i][zd][w][f];
                	last_water=w;
                	last_food=f;
                	last_day=char(i);
				}
            }
    }
    stack<node> s;
//    freopen("outputQ2.txt","w",stdout);
    printf("ans:%d\n",ans);
    printf("day:%d weather:%d point:%d water:%d food:%d\n",last_day,weather[Day],zd,last_water,last_food);
    
    node temppath=(node){
    
    last_day,zd,last_water,last_food};
    s.push(temppath);
    
	while(lastpath!=path[0][1][0][0])
    {
    
    
        s.push(lastpath);
        printf("day:%d weather:%d point %d water:%d food:%d\n",lastpath.day,(int)weather[lastpath.day],(int)mp[lastpath.from],lastpath.water,lastpath.food);
        temppath=lastpath;
        lastpath=path[lastpath.day][lastpath.from][lastpath.water][lastpath.food];
    }
}

2.2 Simplified map + Dijkstra

2.2.1 Model simplification and analysis

The original map of the game is relatively complex, but in fact the only meaningful nodes are the start point, end point, village and mine, so consider using Dijkstra when solving the solution to find the shortest path of these four types of nodes, and compress the original map to only contain four class node.
The following discusses and analyzes each problem.
For the situation where there is only one player and all the weather is known every day: the first level and the second level must have definite optimal solutions, and the map structure is not complicated, so you can directly pass the poor It can be solved by search strategies such as lifting and Monte Carlo.

2.2.2 Model assumptions

1. Daily weather conditions are independent of each other.
2. Players determine their strategy every morning, and complete state transfer and resource and fund settlement at night.
3. In a multiplayer game, each player is absolutely selfish and completely rational.

2.2.3 Symbol description

insert image description here

2.2.4 Model establishment and solution

				maxQ30+12pwW30+12pfF30

Among them, Qt, Wt, and Ft represent the amount of funds, water, and food left by the player on day t, respectively. If the player reaches the finish line before the 30th day, all attributes will be considered unchanged in the next few days, so we use the 30th day as the unified end time. The objective function has the following constraints: Qt=Qt−1+QMineMinet−Shopt[2pfShopFt+2pwShopWt] The fund at the end of each day
in terms of food
is equal to the fund of the previous day plus the 1000 yuan obtained by mining on the day (if mining), and then Subtracts the money spent on buying food and water in the village (if purchased). Among them, ShopFt and ShopWt represent the amount of food and water (if purchased) purchased by the player on day t, respectively.

Ft=F(t−1)−2Movet △Ft− 3Mine tMovet △Ft−(1−Movet−Minet)△Ft+Shopt ShopFt

water aspect

Wt=Wt−1−2Movet△Wt−3Minet△Wt−(1−Movet−Minet)△Wt+ShoptShopWt

2.2.5 Map simplification

We first introduce Dijkstra's algorithm, which is an efficient algorithm for finding the shortest path between two points in a directed weighted graph. Select the start point, end point, village and mine in the picture as special points, and use Dijkstra's algorithm to calculate the shortest path between every two special points (that is, the minimum number of days required without considering the influence of sandstorm weather). Then complete a new map based on the simplified situation.
insert image description here

# encoding: utf-8
# init_water=180
# init_food=330
init_water=184
init_food=324
money=10000-init_food*10-init_water*5


weather=["高温","高温","晴朗","沙暴","晴朗",
         "高温","沙暴","晴朗","高温","高温",
         "沙暴","高温","晴朗","高温","高温",
         "高温","沙暴","沙暴","高温","高温",
         "晴朗","晴朗","高温","晴朗","沙暴",
         "高温","晴朗","晴朗","高温","高温"
         ]

base_consume_water=[5,8,10]
base_consume_food=[7,6,10]

def get_weather(i):
    if i=="高温":
        return 1
    if i=="晴朗":
        return 0
    else:
        return 2

def go(hhday,road):

    already_go=0
    consume_water=0
    consume_food=0
    while already_go<road:
        if hhday>30:
            return -1,-1,-1
        if get_weather(weather[hhday-1])!=2:
            #print(hhday,"Day go",weather[hhday])
            consume_food+=base_consume_food[get_weather(weather[hhday-1])]*2
            consume_water+=base_consume_water[get_weather(weather[hhday-1])]*2
            hhday+=1
            already_go+=1
        else:
            #print(hhday, "Day dont go")
            consume_food += base_consume_food[get_weather(weather[hhday-1])]
            consume_water += base_consume_water[get_weather(weather[hhday-1])]
            hhday += 1
    return consume_water,consume_food,hhday

base_water_price=5
base_water_weight=3
base_food_price=10
base_food_weight=2

def possess_c(cur_water,cur_food,cur_money,cur_day,log):
    can_take=1200-cur_water*3-cur_food*2
    #print(can_take)
    #print(cur_money)
    log=log+"At Day "+str(cur_day)+": "+"Reach c water and food "+str(cur_water)+" "+str(cur_food)+"\n"
    i=0
    if cur_day>18:
        # 准备返程 尽可能只携带足以到达终点的物资
        temp_water=max(36,cur_water)
        temp_food=max(40,cur_food)
        i=temp_water-cur_water
        j=temp_food-cur_food
        temp_money = cur_money - i* base_water_price * 2-j*base_food_price*2
    else:
        # 由于起始点倾向于购买性价比更好的食物,所以这里倾向于购买水已装满背包
        i=int(can_take/base_water_weight)
        j=0
        temp_water=cur_water+i
        temp_food=cur_food
        temp_money=cur_money-i*base_water_price*2

    newlog=log+"At Day "+str(cur_day)+": "+"Buy water and food "+str(i)+" "+"\n"
    q,w,e=go(cur_day,3)
    temp_water1=temp_water-q
    temp_food1=temp_food-w
    newlog+="At Day "+str(e)+": "+"Move End water and food "+str(temp_water1)+" "+str(temp_food1)+"\n"
    possess_z(temp_water1,temp_food1,temp_money,e,newlog)

    newlog = log+"At Day "+str(cur_day)+": "+"Buy water and food "+str(i)+ "\n"
    q, w, e = go(cur_day, 2)
    temp_water2 = temp_water - q
    temp_food2 = temp_food - w
    newlog += "At Day " + str(e) + ": " + "Move Mine water and food " + str(temp_water2) + " " + str(
        temp_food2) + "\n"
    posseess_k(temp_water2, temp_food2, temp_money, e,newlog)


log_list={
    
    }
def possess_z(cur_water,cur_food,cur_money,cur_day,log):
    #print("END ",cur_water*5/2+cur_food*10/2+cur_money,cur_day)
    log+="End "+str(cur_day)+" "+str(cur_water*5/2+cur_food*10/2+cur_money)
    if cur_water<0 or cur_food<0:
        return -1
    log_list[log]=cur_water*5/2+cur_food*10/2+cur_money
    return cur_water*5/2+cur_food*10/2+cur_money

def posseess_k(cur_water,cur_food,cur_money,cur_day,log):
    log = log + "At Day " + str(cur_day) + ": " + "Reach M water and food " + str(cur_water) + " " + str(
        cur_food) + "\n"
    water_limit=cur_water/(base_consume_water[get_weather("晴朗")]*3)
    food_limit=cur_food/(base_consume_food[get_weather("晴朗")]*3)
    total_limit=int(min(water_limit,food_limit))
    total_limit=min(total_limit,30-cur_day)

    for i in range(1,total_limit+1):
        temp_food=cur_food
        temp_water=cur_water
        temp_day=cur_day
        newlog=log
        temp_money=cur_money

        for j in range(1,i+1):
            temp_water=temp_water-base_consume_water[get_weather(weather[cur_day+j-2])]*3
            temp_food=temp_food-base_consume_food[get_weather(weather[cur_day+j-2])]*3
            temp_day+=1
            temp_money+=1000
            newlog+="At Day " + str(temp_day) + ": " + "Dig " + str(j)+" Days "+str(temp_water) + " " + str(
            temp_food) +" " + str(temp_money)+ "\n"


        q, w, e = go(temp_day, 2)
        if q < 0:
            continue
        temp_water2 = temp_water - q
        temp_food2 = temp_food - w

        if temp_food2 < 0 or temp_water2 < 0:
            continue
        newlog += "At Day " + str(e) + ": " + "Go Village water and food " + str(temp_water2) + " " + str(
            temp_food2) + "\n"
        possess_c(temp_water2, temp_food2, temp_money, e, newlog)

        q,w,e=go(temp_day,5)
        if q<0:
            continue
        temp_water1=temp_water-q
        temp_food1=temp_food-w


        if temp_food1<0 or temp_water1<0:
            continue

        newlog += "At Day " + str(e) + ": " + "Go end water and food " + str(temp_water1) + " " + str(
            temp_food1) + "\n"
        possess_z(temp_water1,temp_food1,temp_money,e,newlog)


def check(i,j):
    if 3*i+2*j>1200 or 5*i+10*j>10000:
        return False
    else:
        return True

def train():
    i=0
    for init_water in range(150,200):
        for init_food in range(300,360):
            i+=1
            if check(init_water, init_food):
                q,w,e=go(1,6)
                log=""
                possess_c(init_water-q,init_food-w,money,e,log)
    print(i)
train()
max=-1
max_index=0
for i in log_list:
    if log_list[i]>max:
        max=log_list[i]
        max_index=i
print(max_index)

3. The third level and the fourth level

Compared with the first two levels, the third level and the fourth level only know the weather of the day, so as to decide the action plan of the day and give the best strategy.

3.1 Summary of the first two levels

Analysis of the first level and the second level: the following basic policy design principles can be drawn
(1) the resources at the end point are just exhausted. In order to get as much funds as possible when reaching the end point, there is no reason for the universal joint to buy excess water and food for survival. The price of resources purchased by players at 7:00 and the village is higher than the funds returned at the end point, so when the weather conditions are known In this case, the player knows the minimum resources needed to maintain their own survival, so they have the ability to control the resources to be exhausted when they reach the end. This strategy is only applicable when the global weather is known. The third and fourth levels are not allowed.
(2) Buy more food at the starting point to ensure survival.
Because the resources in the village are expensive, buy food as much as possible at the starting point, and because the backpack has an upper limit, players tend to buy more expensive and lower-quality resources at the starting point. Will buy as much food as possible.

3.2 Three levels

Due to the randomness of the third and fourth rounds, it is impossible to give a deterministic optimal strategy, so after the design of the plan, it is necessary to evaluate the results of the plan. The third step is to be dealt with while using the idea of
​​dynamic programming .
Off weather is random. However, the map is relatively small and only has 10 days. All the weather conditions can be provided for 1024 situations. Dynamic programming can be used to give the optimal solution for each situation, and statistical methods can be used to observe the rules.
By observing the optimal solution strategy, it is found that even in all sunny conditions, not all mines are mined. It can be guessed that this level cannot be mined.
In fact, because there is no village in the third level, and because the high temperature weather consumes more and the mining income is smaller, even if mining in sunny weather, the income is only 200-165=35, and the income of mining for five days is 175. The resource loss caused by the detour cannot be compensated. So going directly to the end point is a more correct choice.

3.3 Four levels

The fourth level of analysis introduces a new conceptual decision point to the previous levels. This decision point 13 is only 4 days away from the starting point, and it is a must pass point for players in the desert, which is very similar to the situation in the third level. At the same time, the decision point is only one day's journey away from the village and the mine. The decoration at the decision point directly affects the player's decision, so it is the key point for the player to make a decision. Analyze the situation where there are no mines and villages in
the most strategic map in general

When the player is close to the next destination, the player should not wait, and should try to reach the destination as much as possible, because a longer stay will greatly increase the consumption of resources, and even the risk of failure, even if the wait can finally arrive The finish line, the final funds and the fast-pass package are not much different, and the money saved by avoiding walking in the heat is not much.
If there are villages and mines on the map,
the starting point strategy is to carry high-efficiency resources, and replenish resources in villages with low efficiency. The
action strategy is to make decisions at points close to villages and mines, and replenish resources first if there are few resources. , if there are more resources, go to mine. When the remaining resources are found by mining, the worst plan is only enough to go to the next function point.

3.4 How to deal with the weather

The idea of ​​​​handling the weather is that it is randomly generated according to a certain distribution mentioned above, and then the most effective strategy is analyzed by statistics for each situation.
Another is to use the Markov chain to establish a weather forecast model. Predict the weather conditions of the remaining levels according to the weather conversion of the first level. According to the model of problem 1, the player's best strategy under different weather conditions can be obtained. Using the corresponding weather condition probability and the maximum funds under the optimal strategy, we can get Calculate the mathematical expectation of the final income, and choose a strategy with the largest mathematical expectation

4. Using software and programming languages

Use different tools according to different ideas to solve the problem;
if dynamic programming is used as the main solution method, then C++ and MATLAB can be used as the solution method.
If you focus on simulation and simulation, use Monte Carlo to solve it. It can be done using Python.
If you use a solver such as groubi, you can use it with MATLAB and programming languages.

In the second part of this article, the code for dynamic programming to solve the first and second levels comes from

https://www.cnblogs.com/cherrypill/p/15158527.html

Guess you like

Origin blog.csdn.net/qq_21561833/article/details/122783459