Review and summarize the dp algorithm of writing algorithms every day

Personal understanding: The dp algorithm is an ideal state algorithm. Assuming that all actions before this time are optimal, then select the most likely situation that connects this state (that is, the last action) plus this time The reward of the situation, then it is the best in the current state.

To sum up, it is mainly for simple template questions. These questions are extracted from the acm step of hdu.
In fact, each dp algorithm needs a dp array, whether it is one-dimensional or two-bit, to save the optimal state so far.

You can summarize a formula. In the dp question type, there are basically formulas in the following form.
                                    dp[i][j] = max(dp[i][j], dp[i-1][j] or dp[i][j-1] or both)
Another point to note is the given initial value. Here are some topics:

FatMouse's Speed
This problem is to find the longest eligible mouse, and write down the number:

Code first:
#include <iostream>  
#include <iomanip>  
#include<queue>  
#include<math.h>  
#include<algorithm>  
#include<string.h>  
#include<stdlib.h>  
#include<stdio.h>  
#include<iomanip>  
#include<string.h>  
#include<sstream>  
#include<string>  
//define function section  
#define repf(i,a,b) for(int i =(a);i<(b);i++)  
using namespace std;  
  
struct mouse{  
public :  
    int num ;  
    int weight;  
    int speed ;  
};  
  
bool cmp(mouse a ,mouse b )  
{  
    if(a.weight==b.weight)  
        return a.speed>b.speed;  
    return a.weight<b.weight;  
}  
struct node{  
public :  
    int num;//How many mice that meet the requirements before the record  
    int pre;  
} dp[1000];  
  
mouse mice[1000];  
int main() {  
  
   int index = 0 ;  
   while(cin>>mice[index].weight&&cin>>mice[index].speed)  
   {  
       mice[index].num=index+1;  
       index ++ ;  
   }  
   repf(i,0,1000)  
   {  
       dp[i].num = 1;//How many mice are on the string that meets the above requirements and includes itself  
       dp[i].pre = 0;  
   }  
  
   sort(mice,mice+index,cmp);  
   int Max = 0 ,beginIndex;  
   repf(i,0,index)  
   {  
       repf(j,0,i)  
       {  
           //Determine whether it is the requirement of the top layer of radiation  
           if(mice[j].speed>mice[i].speed&&mice[j].weight<mice[i].weight)  
           {  
               //See if the length is small, then you can add  
               if(dp[i].num<dp[j].num+1)  
               {  
                   //Update the longest node count  
                   dp[i].num=dp[j].num+1;  
                   //Update the position of the previous mouse  
                   dp[i].pre=j;  
               }  
           }  
       }  
       //update max  
       if(dp[i].num>Max)  
       {  
           Max=dp[i].num;  
           beginIndex = i ;  
       }  
   }  
//This is actually completely unnecessary, a direct loop is the result.  
   int m[1000];  
   repf(k,0,Max)  
   {  
       m[k] = beginIndex;  
       beginIndex = dp[beginIndex].pre;  
   }  
   // output count  
   cout << Max<<endl;  
   // output path  
   for(int k = Max-1;k>=0;k--)  
   {  
       cout << mice[m[k]].num<<endl;  
   }  
  
  
    return 0;  
}  

The dp used in this topic is at this location:
  //See if the length is small, then you can add 
               if(dp[i].num<dp[j].num+1) 
               { 
                   //Update the longest node number 
                   dp[i].num=dp[j] .num+1; 
                   //Update the position of the previous mouse 
                   dp[i].pre=j; 
              } 
Although it is a bit deformed, because it is necessary to record the predecessor of dp[i].pre, it cannot be written as a max to get the result.
And what everyone needs to remember in this is that the best state of each time is based on the last time, and this cannot be obvious to the last time (which one is the last time? The longest, although it is the best state, I don't know), this kind of structure for i..... for j ; j<i ; is needed, let's look at the second topic. 
destiny
The above code, this topic is very close to the people, the dp of each current state is the largest of the previous dp plus the current reward value
Above code:
#include <iostream>  
#include <iomanip>  
#include<queue>  
#include<math.h>  
#include<algorithm>  
#include<string.h>  
#include<stdlib.h>  
#include<stdio.h>  
#include<iomanip>  
#include<string.h>  
#include<sstream>  
#include<string>  
//define function section  
#define repf(i,a,b) for(int i =(a);i<(b);i++)  
using namespace std;  
const int inf = -1000;  
int data[21][1001];  
int dp[21][1001];  
  
  
  
int main() {  
    int num,r,c,Max ;  
  
    cin>>num;  
    while(num--){  
    cin >> r >> c ;  
    for(int i = 1 ; i <=r;i++)  
    {  
        for(int j = 1 ;j <= c ; j++)  
        {  
            cin>>data[i][j];  
        }  
    }  
    memset(dp,0,sizeof(dp));  
  
    for(int i = 1 ; i <= r ; i ++)  
    {  
        for(int j = 1 ; j <=c ; j ++)  
        {  
            if(i==1&&j==1)  
            {  
                dp[i][j]=data[i][j];  
                continue ;  
            }  
            Max = -1000;  
            for(int k = 1 ; k <j ;k++)  
            {  
                if(j%k==0)  
                {  
                    Max=max(Max,dp[i][k]);  
                }  
            }  
            if(i-1>=1)  
            {  
             Max = max(Max,dp[i-1][j]);  
            }  
            if(j-1>=1)  
            {  
             Max = max(Max,dp[i][j-1]);  
            }  
             dp[i][j] = Max+data[i][j];  
  
  
        }  
    }  
    cout << dp[r][c] <<endl;  
    }  
    return 0;  
}

Next topic:

free pie


This topic is still two daily for loops. The information before and after the topic is very clear. The code is as follows:
#include <iostream>  
#include <iomanip>  
#include<queue>  
#include<math.h>  
#include<algorithm>  
#include<string.h>  
#include<stdlib.h>  
#include<stdio.h>  
#include<iomanip>  
#include<string.h>  
#include<sstream>  
#include<string>  
//¶¨Ò庯Êý¶Î  
#define repf(i,a,b) for(int i =(a);i<(b);i++)  
#define repfe(i,a,b) for(int i =(a);i<=(b);i++)  
using namespace std;  
const int inf = -1000;  
 int data[100001][12];  
 int dp[100001][12];  
  
int main() {  
    int num,position,t,Max,MaxT = 0,tempDp = -1;  
  
    while(cin>>num&&num!=0)  
    {  
        memset(data,0,sizeof(data));  
        repfe(i,1,num)  
        {  
            cin>> position>> t ;  
            if(t>MaxT)  
            {  
              MaxT = t ;  
            }  
            data[t][position] ++;  
  
        }  
        memset(dp,0,sizeof(data));  
        dp[1][4] = data[1][4];  
        dp[1][5] = data[1][5];  
        dp[1][6] = data[1][6];  
        repfe(i,2,MaxT)  
        {  
            repf(j,0,11)  
            {  
                 tempDp = -1 ;  
                tempDp = max(tempDp,dp[i-1][j]);  
                if(j<10)  
                tempDp = max(tempDp,dp[i-1][j+1]);  
                if(j>0)  
                tempDp = max(tempDp,dp[i-1][j-1]);  
                dp[i][j] = tempDp + data[i][j];  
              //  cout << j <<" " << i <<" "<<dp[j][i]<<endl;  
            }  
        }  
  
        int res = 0 ;  
        repf(i,0,12)  
        {  
            if(dp[MaxT][i]>res)  
            {  
                res = dp[MaxT][i];  
            }  
        }  
        cout <<res <<endl;  
  
    }  
  
    return 0;  
}  

There are two pits in this problem. One is that when you initialize it correctly, it is not all 0s and you are done. The other is that you need to figure out the order of loop nesting, whether it is time or position first.

Next:
Directly on the address: click to open the link
This problem is that there is no clear before and after information, you need to find it yourself, that is, the kind of cycle of j<i.

Guess you like

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