Luogu P1941 [NOIP2014 improvement group] flying birds

Luogu P1941 [NOIP2014 improvement group] flying birds

Title Description

Flappy Bird is a popular casual mobile game. Players need to constantly control the frequency of clicking on the mobile phone screen to adjust the flying height of the bird, so that the bird can smoothly pass through the pipe gap on the right side of the screen. If the bird accidentally hits the water pipe or falls to the ground, it will fail.

In order to simplify the problem, we simplified and adapted the rules of the game:

The game interface is a two-dimensional plane with a length of nn and a height of mm, in which there are kk pipes (ignoring the width of the pipes).

Birds always move within the game interface. The bird starts from any integer height on the far left of the game interface, and when it reaches the far right of the game interface, the game is completed.

The distance that the bird moves right in the abscissa direction per unit time is 11, and the vertical distance is controlled by the player. If you click the screen, the bird will rise to a certain height xx. You can click multiple times per unit time, and the effect is superimposed; If you don't click on the screen, the bird will descend to a certain height yy. When the bird is at different positions in the abscissa direction, the rising height xx and the falling height yy may be different from each other.

When the height of the bird is equal to 00 or the bird touches the pipe, the game fails. When the height of the bird is mm, it cannot rise again.

Now, please judge whether you can complete the game. If possible, output the minimum number of clicks; Otherwise, the maximum number of pipe gaps that the output bird can pass through.

Input format

There are 33 integers n, m, kn, m and K in line 11, which respectively represent the length, height and number of water pipes of the game interface, and each two integers are separated by a space;

In the next nn line, 22 integers xx and yy separated by a space in each line represent the height xx of the bird in the next position after the player clicks the screen at the abscissa position 0 \sim n-10 ∼ n − 1, and the height yy of the bird in the next position when the player does not click the screen at this position.

Next kk line, 33 integers per line, p,l,hp,l,h, separated by a space between each two integers. Each line represents a pipe, where pp represents the abscissa of the pipe, ll represents the height of the lower edge of the pipe gap, and hh represents the height of the upper edge of the pipe gap (the input data ensure that pp is different, but it is not guaranteed to be given in size order).

Output format

Two lines in total.

The first line contains an integer. If the game can be completed successfully, 11 is output, otherwise 00 is output.

The second line contains an integer. If the first line is 11, the minimum number of clicks required to successfully complete the game will be output. Otherwise, the maximum number of pipe slots that the bird can pass through will be output.

analysis:

  • First of all, because this problem has traces from the beginning to the end (each step can be deduced from the previous step), we can do it with dynamic programming
  • In the process of rising, birds can fly many times at a time (pay attention to the problem, you can keep clicking on the screen during the rising process at the same time) --- complete backpack
  • In the descending process, birds can only descend once at a time, --------- 01

difficulty

  • Pipeline, if there is no pipeline here?
  • Does the traversal start from 1 or 0? yes f o r ( i = 1 ; i < = n ; i + + ) for(i=1;i<=n;i++) For (I = 1; I < = n; I + +) or f o r ( i = 0 ; i < = n ; i + + ) for(i=0;i<=n;i++) For (I = 0; I < = n; I + +) or f o r ( i = 0 ; i < n ; i + + ) for(i=0;i<n;i++) for(i=0;i<n;i++)??
  • All the way up to the top. How to analyze this

solve

Haha, if you encounter the above problems, don't panic, because I've been thinking about these problems for a long time

  • This is reflected in the code

  • In fact, there is not much difference between starting from 0 and starting from 1. It mainly depends on whether the storage location and operation location are right

    Note that looking at the figure, there is a length of 10, and there are 11 points from 0 – 10 (but because the end is), because we use bag[11] to represent these 11 points, when i = 0 i=0 i=0 is the first column, and i=10 is the last column.

Primary code 1
#include"iostream"
#include"bits/stdc++.h"
using namespace std;
const int maxn=10000+5;
int x[maxn],y[maxn],up[maxn],down[maxn];
int bag[maxn][2005];//Backpacks are used to store data.
int flag[maxn]={0};//Used to judge whether there is a pipeline here
int n,m,k;//Number of long height water pipes

void dp()
{
    for(int i=1;i<=n;i++){//Traversal length
        if(flag[i]==0){//If there is no pipe here, then change, up[i],down[i],
                up[i]=m+x[i];
                down[i]=1;
            }
        
        for(int j=down[i];j<=up[i];j++){
            bag[i][j]=min(bag[i][j-x[i]]+1,bag[i-1][j-x[i]]+1);
            //If this value is used in the next cycle, the value must be the minimum. If it rises, the minimum value is the ability. If it falls, the minimum value is the same
            //bag[i][j]=min(bag[i][j],bag[i][j+y[i]) / / this cannot be done because the value of decreasing the change to bag may be used
            //If (J > m) bag [i] [M] = min (bag [i] [J], bag [i] [M]); / / I still feel there is a problem
        }

        for(int j=m+1;j<=x[i]+m;j++)bag[i][m]=min(bag[i][m],bag[i][j]);//Exceeding the maximum height
        for(int j=down[i];j<=min(up[i],m);j++){
            if(j+y[i]>m)bag[i-1][j+y[i]]=0x3f3f3f3f;//Because it exceeds m, we must not be able to reach it
            bag[i][j]=min(bag[i][j],bag[i-1][j+y[i]]);
        }
    }
    
    //Final output

    int ans=0x3f3f3f3f;
    for(int i=1;i<=m;i++)ans=min(bag[n][i],ans);

    if(ans!=0x3f3f3f3f)cout<<1<<endl<<ans;

    else{
        int i,j;
        for(i=n;i>=1;i--){
            for(j=1;j<=m;j++)if(bag[i][j]<0x3f3f3f3f)break;
                if(j<=m)break;//Because if the inner loop ends naturally, then j==0
        }
        int ans=0;
        for(int kk=1;kk<=i;kk++){
            if(flag[kk]==1)ans++;
        }
        cout<<0<<endl<<ans;
    }
}
int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];//Ascending height, descending height.
    }
    int x;//Abscissa
    for(int i=1;i<=k;i++){
        cin>>x;
        cin>>down[x]>>up[x];//Bottom edge height
        down[x]++;//If you enter 1, then 2 can pass
        up[x]--;//If you enter 2. Then 1 can pass
        flag[x]=1;//Is there a pipe at this location
    }

    memset(bag,0x3f3f3f3f,sizeof(bag));

    for(int i=1;i<=m;i++)bag[0][i]=0;//First line, initialize

    dp();
    return 0;
} 

But this code is problematic and not perfect

Ultimate code 2
#include"iostream"
#include"bits/stdc++.h"
using namespace std;
const int maxn=10000+5;
int x[maxn],y[maxn],up[maxn],down[maxn];
int bag[maxn][2005];//be careful
int flag[maxn]={0};
int n,m,k;//Number of long height water pipes

void dp()
{
    for(int i=1;i<=n;i++){
          
        for(int j=x[i];j<=x[i]+m;j++)bag[i][j]=min(bag[i][j-x[i]]+1,bag[i-1][j-x[i]]+1);//rise

        for(int j=m+1;j<=x[i]+m;j++)bag[i][m]=min(bag[i][m],bag[i][j]);//If the maximum height is exceeded, handle it

        for(int j=1;j<=m-y[i];j++)bag[i][j]=min(bag[i][j],bag[i-1][j+y[i]]);//The reason why the descent is compared with bag[i][j] is to compare the position reached by the previous ascent

        if(flag[i]==1){//If there's a water pipe here

            for(int j=1;j<down[i];j++)bag[i][j]=0x3f3f3f3f;

            for(int j=up[i]+1;j<=m;j++)bag[i][j]=0x3f3f3f3f;
        }
        

    int ans=0x3f3f3f3f;
    for(int i=1;i<=m;i++)ans=min(bag[n][i],ans);

    if(ans!=0x3f3f3f3f)cout<<1<<endl<<ans;

    else{
        int i,j;
        for(i=n;i>=1;i--){
            for(j=1;j<=m;j++)if(bag[i][j]<0x3f3f3f3f)break;
                if(j<=m)break;//Because if the inner loop ends naturally, then j==0
        }
        int ans=0;
        for(int kk=1;kk<=i;kk++){
            if(flag[kk]==1)ans++;
        }
        cout<<0<<endl<<ans;
    }
}
int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];//Ascending height, descending height.
    }
    int x;//Abscissa
    for(int i=1;i<=k;i++){
        cin>>x;
        cin>>down[x]>>up[x];//Bottom edge height
        down[x]++;//If you enter 1, then 2 can pass
        up[x]--;//If you enter 2. Then 1 can pass
        flag[x]=1;//Is there a pipe at this location
    }

    memset(bag,0x3f3f3f3f,sizeof(bag));

    for(int i=1;i<=m;i++)bag[0][i]=0;

    dp();
    return 0;
}
  • You can see that there are many for in the final code, but in fact, the time complexity is the same as the first one O ( n 2 ) O(n^2) For O(n2), there are already n layers of loops. In fact, we add loops in the non innermost layer for, which are almost the same.

If you have any questions, you can leave a message below

Tags: Algorithm

Posted on Mon, 22 Nov 2021 01:31:40 -0500 by nova912