Number division (dfs, dp)

any door

[NOIP2001 Improvement Group] Division of numbers

topic description

the integer nnn is divided intokkk copies, and each copy cannot be empty, and any two schemes are different (regardless of the order).

For example: n = 7 n=7n=7 k = 3 k=3 k=3 , the following three divisions are considered to be the same.

1 , 1 , 5 1,1,5 1,1,5;
1 , 5 , 1 1,5,1 1,5,1;
5 , 1 , 1 5,1,1 5,1,1.

Ask how many different divisions there are.

input format

n , k n,k n,k 6 < n ≤ 200 6<n \le 200 6<n2002 ≤ k ≤ 6 2 \le k \le 62k6

output format

1 1 1 integer, that is, different divisions.

Example #1

Sample Input #1

7 3

Sample output #1

4

hint

The four divisions are:
1 , 1 , 5 1,1,51,1,5;
1 , 2 , 4 1,2,4 1,2,4;
1 , 3 , 3 1,3,3 1,3,3;
2 , 2 , 3 2,2,3 2,2,3.

[source of topic]

The second question of NOIP 2001 improvement group

This question is very simple, that is, thinking

Writing method 1:
Although dfs is not as fast as dp, the amount of data in this question is very small. If both dp and dfs can pass during the competition, it is best to use dfs. The code is easy to write and easy to correct.

Here, because of non-repetition, you can record each division in ascending order: record the number used in the last division, and ensure that the number used in the current division is not less than the score used in the last division. When the number of divisions is equal to k, compare the total of the division. Whether the points are the same as n and record the number of times.

One pruning that has to be done is that when enumerating the scores used in the current division, it should be enumerated from last (the score used in the last division) to sum+i*(k-cur)<=n, because the scores divided later must be greater than Or equal to the fraction used for the current division.

#include<cstdio>

int n,k,cnt;

void dfs(int last,int sum,int cur)
{
    
    
    if(cur==k)
    {
    
    
        if(sum==n) cnt++;
        return;
    }
    for(int i=last;sum+i*(k-cur)<=n;i++)//剪枝,只用枚举到sum+i*(k-cur)<=n为止
        dfs(i,sum+i,cur+1);
}

int main()
{
    
    
    scanf("%d%d",&n,&k);
    dfs(1,0,0);
    printf("%d",cnt);
}

Writing method two: dp

solution【i】【j】represents the number of cases shared by j groups when the sum of the numbers is i.

Since no matter what the sum of the numbers is, dividing them into 0 groups is a case of 0, and dividing them into a group is a case,

So when j=0, all should be initialized to 0, and when j=1, all should be initialized to 1.

At the same time, no matter how many groups are divided into, the sum of numbers is 0 and 1 is 0 (except i=j=1)

So when i=0 or i=1, j is all initialized to 0 from 2.

For any remaining solution [i] [j], it can be obtained in the following way:

Solution [i] [j] = all cases where the first number is 1 + all cases where the first number is not 1.

When the first number is 1, it is already determined that 1 occupies 1 position and occupies 1 of the total number.

Therefore, all cases where the first number is 1 = solution [i-1] [j-1].

When the first number is not 1, it can be regarded as adding a 1 to all positions and then using the new total number to find the number of times for all positions.

So it is decided that the total number of j is occupied, and the position is still j, which is unchanged from the original.

Therefore, all cases where the first number is not 1 = solution [ij] [j].

Because solution[i][j]=solution[i-1][j-1]+solution[ij][j].

 #include<cstdio>
        using namespace std;
        int main()
        {
    
    
            int solution[205][10];
            int n,k,i,j;
            scanf("%d %d",&n,&k);
            for(i=1;i<=n;i++)
            {
    
    
                solution[i][1]=1;
                solution[i][0]=0;
            }
            for(i=2;i<=k;i++)
            {
    
    
                solution[1][i]=0;
                solution[0][i]=0;
            }
            for(i=2;i<=n;i++)
                for(j=2;j<=k;j++)
                    if(j>i)
                        solution[i][j]=0;
                    else
                        solution[i][j]=solution[i-1][j-1]+solution[i-j][j];
            printf("%d",solution[n][k]);
            return 0;    
}

Guess you like

Origin blog.csdn.net/qq_51408826/article/details/127561998