Fragen zur mathematischen Modellierung 2020B in der Wüste

1. Thema

Betrachten Sie das folgende kleine Spiel: Mit einer Karte verwendet der Spieler das Anfangskapital, um eine bestimmte Menge Wasser und Lebensmittel (einschließlich Lebensmittel und andere Dinge des täglichen Bedarfs) zu kaufen, und beginnt vom Startpunkt aus, in die Wüste zu wandern. Unterwegs werden Sie unterschiedlichem Wetter begegnen, und Sie können auch in Minen und Dörfern Geld oder Ressourcen auffüllen. Das Ziel ist es, das Ende innerhalb der angegebenen Zeit zu erreichen und so viel Geld wie möglich zu behalten.
Die Grundregeln des Spiels sind wie folgt:
(1) Nimmt man Tage als grundlegende Zeiteinheit, beginnt das Spiel am Tag 0, und der Spieler befindet sich am Startpunkt. Ein Spieler muss die Ziellinie am oder vor Ablauf der Frist erreichen, danach endet das Spiel des Spielers.
(2) Zwei Ressourcen, Wasser und Nahrung, werden benötigt, um die Wüste zu durchqueren, und ihre kleinste Maßeinheit ist eine Kiste. Die Summe der Qualität von Wasser und Nahrung, die der Spieler jeden Tag besitzt, darf die Gewichtsgrenze nicht überschreiten. Wenn der Zielpunkt nicht erreicht wird und das Wasser oder die Nahrung aufgebraucht sind, gilt das Spiel als gescheitert.
(3) Das tägliche Wetter ist eine der drei Bedingungen „klar“, „hohe Temperatur“ und „Sandsturm“, und das Wetter ist in allen Gebieten der Wüste gleich.
(4) Spieler können jeden Tag von einem Bereich auf der Karte in einen anderen angrenzenden Bereich gehen oder an Ort und Stelle bleiben. Sandsturmtage müssen bleiben.
(5) Die Menge an Ressourcen, die der Spieler verbraucht, der einen Tag lang an Ort und Stelle bleibt, wird als Grundverbrauch bezeichnet, und die Menge an Ressourcen, die durch Gehen an einem Tag verbraucht wird, ist die Zeit des Grundverbrauchs.
(6) Am 0. Tag können die Spieler mit dem Startguthaben Wasser und Lebensmittel zum Grundpreis am Startpunkt kaufen. Spieler können am Startpunkt bleiben oder zum Startpunkt zurückkehren, aber sie können nicht mehrmals am Startpunkt Ressourcen kaufen. Die Spieler können das verbleibende Wasser und Essen nach Erreichen des Endpunkts zurückgeben, und der Rückgabepreis jeder Box beträgt die Hälfte des Grundpreises.
(7) Wenn Spieler sich in der Mine aufhalten, können sie Gelder durch Mining erhalten.Die Menge an Geldern, die sie für einen Tag durch Mining erhalten, wird als Grundeinkommenbezeichnet. Beim Bergbau entspricht die Menge der verbrauchten Ressourcen den Zeiten des Basisverbrauchs; wenn nicht beim Bergbau, ist die Menge der verbrauchten Ressourcen der Basisverbrauch. An dem Tag, an dem Sie in der Mine ankommen, können Sie nicht abbauen. Bergbau ist auch an Sandsturmtagen möglich.
(8) Spieler können die verbleibenden Anfangsgelder oder Gelder aus dem Bergbau verwenden, um jederzeit Wasser und Lebensmittel zu kaufen, wenn sie vorbeikommen oder sich im Dorf aufhalten, und der Preis jeder Kiste ist doppelt so hoch wie der Grundpreis.
Bitte erstellen Sie ein mathematisches Modell entsprechend den verschiedenen Einstellungen des Spiels, um die folgenden Probleme zu lösen.

  1. Unter der Annahme, dass es nur einen Spieler gibt und die Wetterbedingungen während der gesamten Spieldauer jeden Tag im Voraus bekannt sind, versuchen Sie, die optimale Strategie des Spielers unter normalen Umständen anzugeben. Lösen Sie „First Level“ und „Second Level“ im Anhang und tragen Sie die entsprechenden Ergebnisse jeweils in Result.xlsx ein.
  2. Unter der Annahme, dass es nur einen Spieler gibt und der Spieler nur die Wetterbedingungen des Tages kennt, kann er den Aktionsplan für den Tag entsprechend festlegen, versuchen, unter normalen Umständen die beste Strategie für den Spieler zu geben, und die "dritte Ebene" analysieren. und "vierte Ebene" im Anhang. " für eine ausführliche Diskussion.

2. Problemlösungsideen und die erste und zweite Ebene

Es gibt drei Arten von Ideen
1. Dynamische Programmierung
2. Verwenden Sie den Dijkstra-Algorithmus, um
das Problem nach einer kurzen Karte zu lösen. 3. Analysieren Sie das Problem und erstellen Sie dann ein Modell. Verwenden Sie Groubi und Lingo, um die optimale Lösung zu finden

2.1 Dynamische Programmiersituation

Unter der Annahme, dass der Zustand dp[k][j][w][f] das verbleibende Wasser am j-ten Punkt am k-ten Tag darstellt, ist der maximale Vorrat der w-Box und die verbleibende Nahrung die f-Box, dann:

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

2.1.1 Anfangswerteinstellung

Da der Startpunkt Materialien am Startpunkt kaufen kann, gibt es einen Anfangszustand
dp[0][qd][w][f]=10000−Kosten_Wasser∗w−Kosten_Lebensmittel∗fw∈[0,400]f∈[0,600]
wo cost_water​​, cost_food​​​​ Das Geld, das ausgegeben wird, um Wasser und Essen zu kaufen.
Hier wird davon ausgegangen, dass der Start Tag 0 ist und das Wetter am ersten Tag von Tag 0 bis Tag 1 wirkt.

2.1.2 Zustandsübergangsgleichung

Wenn die Person am k-ten Tag im Dorf j ist:

  1. Der k-te Tag ist ein Sandsturm
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. Wetter ohne Sandsturm:
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

Wenn sich die Person am Tag k in meinem j befindet:
Bergbau

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

Tag k ist Sandsturmwetter:

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

Tag k ist kein Sandsturmwetter:

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

Wenn sich die Person am k-ten Tag in einem anderen Gebiet aufhält,
ist am k-ten Tag Sandsturmwetter:

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

Tag k ist kein Sandsturmwetter:

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

2.1.3 Nachdenken über das implizite Bedingungsbeschränkungsmodell

Neben der Rückkehr ins Dorf, um die Vorräte aufzufüllen, gibt es kein Zurück mehr.
Außer Bergbau und Sandstürme werden nicht an Ort und Stelle bleiben.
Nur der kürzeste Weg zwischen Schlüsselpunkten wird genommen

2.1.4 Code

erste Runde

#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;
}

zweites 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 Vereinfachte Karte + Dijkstra

2.2.1 Modellvereinfachung und -analyse

Die ursprüngliche Karte des Spiels ist relativ komplex, aber tatsächlich sind die einzigen sinnvollen Knoten der Startpunkt, der Endpunkt, das Dorf und die Mine. Erwägen Sie also, Dijkstra zu verwenden, wenn Sie die Lösung lösen, um den kürzesten Weg dieser vier Arten von Knoten zu finden, und komprimieren Sie die ursprüngliche Karte so, dass sie nur vier Klassenknoten enthält.
Im Folgenden wird jedes Problem diskutiert und analysiert:
Für die Situation, in der es nur einen Spieler gibt und das ganze Wetter jeden Tag bekannt ist: Das erste Level und das zweite Level müssen definitiv optimale Lösungen haben, und die Kartenstruktur ist nicht kompliziert, also können Sie direkt an den Armen vorbei Es kann durch Suchstrategien wie Lifting und Monte Carlo gelöst werden.

2.2.2 Modellannahmen

1. Die täglichen Wetterbedingungen sind voneinander unabhängig.
2. Die Spieler legen jeden Morgen ihre Strategie fest und schließen die Staatsübertragung sowie die Abrechnung von Ressourcen und Geldern nachts ab.
3. In einem Multiplayer-Spiel ist jeder Spieler absolut egoistisch und völlig rational.

2.2.3 Symbolbeschreibung

Bildbeschreibung hier einfügen

2.2.4 Modellerstellung und Lösung

				maxQ30+12pwW30+12pfF30

Darunter stellen Qt, Wt und Ft die Menge an Geld, Wasser und Essen dar, die der Spieler am Tag t zurückgelassen hat. Wenn der Spieler vor dem 30. Tag die Ziellinie erreicht, gelten alle Attribute in den nächsten Tagen als unverändert, daher verwenden wir den 30. Tag als einheitliche Endzeit. Die Zielfunktion hat die folgenden Beschränkungen: Qt=Qt−1+QMineMinet−Shopt[2pfShopFt+2pwShopWt] Der Vorrat
an Lebensmitteln
am Ende eines jeden Tages entspricht dem Vorrat des Vortages plus den 1000 Yuan, die durch das Mining gewonnen wurden am Tag (bei Bergbau) und subtrahiert dann das Geld, das für den Kauf von Nahrung und Wasser im Dorf ausgegeben wurde (falls gekauft). Darunter repräsentieren ShopFt und ShopWt die Menge an Nahrung bzw. Wasser (falls gekauft), die der Spieler am Tag t gekauft hat.

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

Wasseraspekt

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

2.2.5 Kartenvereinfachung

Wir führen zuerst den Dijkstra-Algorithmus ein, der ein effizienter Algorithmus ist, um den kürzesten Weg zwischen zwei Punkten in einem gerichteten gewichteten Graphen zu finden. Wählen Sie den Startpunkt, den Endpunkt, das Dorf und die Mine im Bild als Sonderpunkte aus und verwenden Sie den Dijkstra-Algorithmus, um den kürzesten Weg zwischen jeweils zwei Sonderpunkten zu berechnen (d. h. die erforderliche Mindestanzahl von Tagen ohne Berücksichtigung des Einflusses des Sandsturmwetters). . Vervollständigen Sie dann eine neue Karte basierend auf der vereinfachten Situation.
Bildbeschreibung hier einfügen

# 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. Die dritte Ebene und die vierte Ebene

Im Vergleich zu den ersten beiden Levels kennen das dritte Level und das vierte Level nur das Wetter des Tages, um den Aktionsplan des Tages zu bestimmen und die beste Strategie zu geben.

3.1 Zusammenfassung der ersten beiden Ebenen

Analyse der ersten Ebene und der zweiten Ebene: Folgende Grundsätze der Politikgestaltung lassen sich ableiten
(1) Die Ressourcen am Endpunkt sind gerade erschöpft. Um beim Erreichen des Endpunkts möglichst viel Geld zu bekommen, gibt es keinen Grund für das Universalgelenk, überschüssiges Wasser und Nahrung zum Überleben zu kaufen.Der Preis für Ressourcen, die von Spielern um 7:00 Uhr gekauft werden, und das Dorf ist höher als der Gelder werden am Endpunkt zurückgegeben, also wenn die Wetterbedingungen bekannt sind. In diesem Fall kennt der Spieler die minimalen Ressourcen, die er benötigt, um sein eigenes Überleben aufrechtzuerhalten, sodass er die Möglichkeit hat, die zu erschöpfenden Ressourcen zu kontrollieren, wenn er das Ende erreicht. Diese Strategie ist nur anwendbar, wenn das globale Wetter bekannt ist. Die dritte und vierte Ebene sind nicht erlaubt.
(2) Kaufen Sie am Startpunkt mehr Lebensmittel, um das Überleben zu sichern.Da
die Ressourcen im Dorf teuer sind, kaufen Sie am Startpunkt so viel Lebensmittel wie möglich, und da der Rucksack eine Obergrenze hat, kaufen die Spieler tendenziell teurer und teurer ein Ressourcen von geringerer Qualität am Ausgangspunkt. Werde so viel Essen wie möglich kaufen.

3.2 Drei Ebenen

Aufgrund der Zufälligkeit der dritten und vierten Runde ist es unmöglich, eine deterministisch optimale Strategie anzugeben, daher ist es nach dem Entwurf des Plans notwendig, die Ergebnisse des Plans zu bewerten.Der dritte Schritt ist während der Verwendung zu
behandeln die Idee der dynamischen Programmierung
Off-Wetter ist zufällig. Allerdings ist die Karte relativ klein und hat nur 10 Tage, es können alle Wetterbedingungen für 1024 Situationen bereitgestellt werden, durch dynamische Programmierung kann für jede Situation die optimale Lösung gefunden werden und mit statistischen Methoden können die Regeln eingehalten werden.
Durch die Beobachtung der optimalen Lösungsstrategie stellt sich heraus, dass auch bei allen Sonnenverhältnissen nicht alle Minen abgebaut werden und man vermuten kann, dass dieses Niveau nicht abgebaut werden kann.
Da es in der dritten Ebene kein Dorf gibt und weil das Hochtemperaturwetter mehr verbraucht und das Bergbaueinkommen geringer ist, beträgt das Einkommen sogar bei sonnigem Wetter nur 200-165 = 35 und das Einkommen des Bergbaus für fünf Tage beträgt 175. Der durch die Umleitung verursachte Ressourcenverlust kann nicht kompensiert werden. Es ist also richtiger, direkt zum Endpunkt zu gehen.

3.3 Vier Ebenen

Die vierte Analyseebene führt einen neuen konzeptionellen Entscheidungspunkt zu den vorherigen Ebenen ein. Dieser Entscheidungspunkt 13 ist nur 4 Tage vom Startpunkt entfernt und ist ein Muss für Spieler in der Wüste, was der Situation im dritten Level sehr ähnlich ist. Gleichzeitig ist der Entscheidungspunkt nur eine Tagesreise vom Dorf und der Mine entfernt.Die Dekoration am Entscheidungspunkt wirkt sich direkt auf die Entscheidung des Spielers aus und ist daher der Schlüsselpunkt für den Spieler, um eine Entscheidung zu treffen.
Analysieren Sie die Situation, in der es auf der strategischsten Karte im Allgemeinen
keine Minen und Dörfer gibt

Wenn sich der Spieler dem nächsten Ziel nähert, sollte er nicht warten und versuchen, das Ziel so weit wie möglich zu erreichen, da ein längerer Aufenthalt den Ressourcenverbrauch und sogar das Risiko des Scheiterns stark erhöht, selbst wenn dies der Fall ist Warten kann endlich ankommen Die Ziellinie, die Endkasse und das Fast-Pass-Paket sind nicht viel anders, und das Geld, das durch das Vermeiden des Gehens in der Hitze gespart wird, ist nicht viel.
Wenn es Dörfer und Minen auf der Karte gibt,
besteht die Startstrategie darin, hocheffiziente Ressourcen zu transportieren und Ressourcen in Dörfern mit geringer Effizienz aufzufüllen.Die Aktionsstrategie besteht darin,
Entscheidungen an Punkten in der Nähe von Dörfern und Minen zu treffen und zuerst Ressourcen aufzufüllen wenn wenig Ressourcen vorhanden sind, wenn mehr Ressourcen vorhanden sind, gehe zu mine Wenn die restlichen Ressourcen durch Mining gefunden sind, reicht der schlechteste Plan nur noch, um zum nächsten Funktionspunkt zu gehen.

3.4 Umgang mit dem Wetter

Die Idee, mit dem Wetter umzugehen, besteht darin, dass es nach einer bestimmten oben genannten Verteilung zufällig generiert wird und dann die effektivste Strategie für jede Situation durch Statistiken analysiert wird.
Eine andere besteht darin, die Markov-Kette zu verwenden, um ein Wettervorhersagemodell zu erstellen. Sagen Sie die Wetterbedingungen der verbleibenden Levels gemäß der Wetterumrechnung des ersten Levels voraus. Gemäß dem Modell von Problem 1 kann die beste Strategie des Spielers unter verschiedenen Wetterbedingungen erhalten werden. Verwenden Sie die entsprechende Wetterbedingungswahrscheinlichkeit und die maximalen Mittel unter optimale Strategie, können wir die mathematische Erwartung des Endeinkommens berechnen und eine Strategie mit der größten mathematischen Erwartung wählen

4. Verwendung von Software und Programmiersprachen

Verwenden Sie unterschiedliche Tools nach unterschiedlichen Ideen, um das Problem zu lösen;
wenn die dynamische Programmierung als Hauptlösungsmethode verwendet wird, können C++ und MATLAB als Lösungsmethode verwendet werden.
Wenn Sie sich auf Simulation und Simulation konzentrieren, verwenden Sie Monte Carlo, um es zu lösen. Dies kann mit Python erfolgen.
Wenn Sie einen Solver wie groubi verwenden, können Sie ihn mit MATLAB und Programmiersprachen verwenden.

Im zweiten Teil dieses Artikels stammt der Code für die dynamische Programmierung zur Lösung der ersten und zweiten Ebene

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

Supongo que te gusta

Origin blog.csdn.net/qq_21561833/article/details/122783459
Recomendado
Clasificación