C++ algorithm basics must brush topic - recursion

recursion

  A recursive algorithm is a simple algorithm, that is, an algorithm that draws intermediate inferences using specific relationships through known conditions until the result is obtained. There are two types of recursion algorithms: forward and backward.

1. Minesweeper MINE

NC20241 Minesweeper MINE

topic description

  I believe everyone has played the game of minesweeper. That is, there are some mines in an n*m matrix, and you need to find out the mines based on some information.
  Halloween is coming, and a simple minesweeping game is popular in the "Yu" people's country. The rules of this game are the same as minesweeping. If there is no mine in a certain grid, then the number in it indicates the number of mines in the grid connected to it.
  Now the chessboard is n×2, some grids in the first column are mines, and there are no mines in the second column, as shown in the figure below: Since the mines in the first column may have multiple solutions to meet the limit of the number of the second column, your The task is to determine how many arrangements there are for the first column of mines based on the information in the second column.

Input description:
The first line has N, the second line has N numbers, which are the numbers in the grid in the second column. (1≤N≤10000)

Output description:
a number, that is, the number of mine placement schemes in the first column.

Example 1
input
2
1 1

output
2

Method 1 Dynamic Programming

Ideas for solving the problem:
1. Use binary to represent the state of the nearby three digits. 1 means there is thunder, and 0 means no. Then there are 8 states in total, 000, 001, 010, 011, 100, 101, 110, 111. The following explains the sample

2. Initially, a[2]={1,1}, when i=0, a[i]=1, then state dp[0][001]=1, dp[0][010]=1, When i=1, a[i]=1, then state dp[1][010]+=dp[0][001], dp[1][100]+=dp[0][010], carefully analyze The transfer relationship is enough, for example, 100 can be obtained by transferring 010 and 110, and 011 can be obtained by transferring 001 and 101, that is, the first two bits are equal to the last two bits of the previous state

code:

#include<bits/stdc++.h>
using namespace std;
int main(){
    
    
    int n;
    int a[10010]={
    
    0};
    int dp[10010][8]={
    
    0};
    cin>>n;
    int ans=0;
    for(int i=1;i<=n;i++){
    
    
        cin>>a[i];
        if(i==1){
    
    //第一个需要初始化
            if(a[i]==0){
    
    
                dp[i][0]++;
            }else if(a[i]==1){
    
    
                dp[i][1]++;
                dp[i][2]++;
            }else if(a[i]==2){
    
    
                dp[i][3]++;
            }
        }else{
    
    //状态转移
            if(a[i]==0){
    
    
                dp[i][0]+=dp[i-1][0]+dp[i-1][4];
            }else if(a[i]==1){
    
    
                dp[i][1]+=dp[i-1][0]+dp[i-1][4];
                dp[i][2]+=dp[i-1][1]+dp[i-1][5];
                dp[i][4]+=dp[i-1][2]+dp[i-1][6];
            }else if(a[i]==2){
    
    
                dp[i][3]+=dp[i-1][1]+dp[i-1][5];
                dp[i][5]+=dp[i-1][2]+dp[i-1][6];
                dp[i][6]+=dp[i-1][3]+dp[i-1][7];
            }else if(a[i]==3){
    
    
                dp[i][7]+=dp[i-1][3]+dp[i-1][7];
            }
        }
    }
    ans+=dp[n][0]+dp[n][2]+dp[n][4]+dp[n][6];//因为最后一个后一位必定是0
    cout<<ans<<endl;
}

Method 2 Recursion

Problem-solving idea:
Let’s change the way of thinking. In fact, if the first two states are fixed, the latter state is actually almost fixed, so we only need to enumerate the first two state bits, and deduce the latter state, if possible. is counted in the answer, that is to say, there are at most 4 options for the answer

code:

#include<bits/stdc++.h>
using namespace std;
int main(){
    
    
    int n;
    int a[10010]={
    
    0};
    int dp[10010]={
    
    0};
    cin>>n;
    for(int i=0;i<n;i++){
    
    
        cin>>a[i];
    }
    int ans=0;
    for(int i=0;i<4;i++){
    
    //枚举四个状态
        dp[0]=i&1;//初始化
        dp[1]=(i>>1)&1;
        if(dp[0]+dp[1]!=a[0]){
    
    
            continue;
        }
        for(int j=1;j<n;j++){
    
    
            dp[j+1]=a[j]-dp[j-1]-dp[j];
            if(dp[j+1]<0||dp[j+1]>1){
    
    //下一位只能是1或者0
                break;
            }
            if(j==n-1&&dp[n]==0){
    
    //符合条件,最后一位必须是0
                ans++;
            }
        }
    }
    cout<<ans<<endl;
}

2. Coke's Flip Game

NC235250 Coke's Flip Game

topic description

  Niu Cola has invented a new type of flipping game!
  On a chessboard with nn rows and mm columns, there is a chess piece placed on each grid, and the color of each chess piece is either black or white. Every time you operate Niu Kele, you can choose a chess piece, flip its color (black to white, white to black), and at the same time flip the color of the four adjacent chess pieces up, down, left, and right (if there are pieces in the corresponding position) .
  Niu Kele would like to ask you to help him judge whether it is possible to turn all chess pieces into black or white through multiple operations? If so, what is the minimum number of operations?

Enter a description:

  The two integers n and m (1≤n≤100, 1≤m≤10) in the first line represent the number of rows and columns of the chessboard.
  After n lines, each line has m numbers. If the i-th number is 0, it means that the chess piece at the corresponding position is white, and if it is 1, it is black.

Output description:

  If it is impossible to turn all chess pieces into one color, output "Impossible" (without quotation marks), otherwise output the minimum number of operations to become one color.

Example 1
Input
4 4
1001
1101
1001
1000

output
4

Problem-solving ideas:
  If the inversion of the first line has been determined, then the operation of the second line will also be determined, because the inversion of the second line needs to invert all the first line to 1 or 0, so we only need Take the flip of the first line and judge whether the flip satisfies the meaning of the question, m<=10, then there are at most 2 10 flip schemes

code:

#include<bits/stdc++.h>
using namespace std;
int getch(int val){
    
    
    int ans=0;
    while(val){
    
    
        ans++;
        val&=(val-1);
    }
    return ans;
}
int main(){
    
    
    int n,m;
    int a[105]={
    
    0};
    int dp1[105]={
    
    0};
    int dp2[105]={
    
    0};
    int ans=0x3f3f3f3f;
    cin>>n>>m;
    for(int i=0;i<n;i++){
    
    
        string b;
        cin>>b;
        for(int j=0;j<m;j++){
    
    
            a[i]*=2;
            if(b[j]=='1'){
    
    
                a[i]+=1;
            }
        }
    }
    for(int i=0;i<(1<<m);i++){
    
    //(1<<m)个状态
        int sum1=0;
        int sum2=0;
        sum1+=getch(i);
        sum2+=getch(i);
        dp1[0]=a[0]^i^(i>>1)^((i<<1)&((1<<m)-1));//全部变1
        dp1[1]=a[1]^i;
        dp2[0]=a[0]^i^(i>>1)^((i<<1)&((1<<m)-1));//全部变0
        dp2[1]=a[1]^i;
        for(int j=1;j<n;j++){
    
    //后面的翻转已近被固定了
            int ch1=dp1[j-1]^((1<<m)-1);
            int ch2=dp2[j-1];
            sum1+=getch(ch1);
            sum2+=getch(ch2);
            dp1[j]=dp1[j]^ch1^(ch1>>1)^((ch1<<1)&((1<<m)-1));
            dp1[j+1]=a[j+1]^ch1;
            dp2[j]=dp2[j]^ch2^(ch2>>1)^((ch2<<1)&((1<<m)-1));
            dp2[j+1]=a[j+1]^ch2;
        }
        if(dp1[n-1]==(1<<m)-1){
    
    //最后一排全部是1
            ans=min(ans,sum1);
        }
        if(dp2[n-1]==0){
    
    //最后一排全部是0
            ans=min(ans,sum2);
        }
    }
    if(ans==0x3f3f3f3f){
    
    
        cout<<"Impossible"<<endl;
    }else{
    
    
        cout<<ans<<endl;
    }
}

Is it very simple?

It will definitely be difficult for newcomers. Do more questions and use them more. Once you get familiar with it, it will be easy. Brother Meng, come on! ! !

There are still deficiencies in the article, welcome to correct me

Thanks for watching, like it

Guess you like

Origin blog.csdn.net/weixin_52115456/article/details/128460505