Dividing the number (DFS, DP)

 

https://www.luogu.com.cn/problem/P1025

Title Description

The integer n into k parts, and each can not be empty, any two schemes are different (regardless of order).

For example: n-=. 7 , K =. 3 , the following three sub-methods are considered the same.

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

Q. How many different points system.

Input Format

n,k (6<n200,2k6)

Output Format

. 1 integer, i.e., different points system.

Sample input and output

Entry 
7 3
Export
4

Description / Tips

Four kinds of points of law:
1,1,5 ;
1,2,4 ;
1,3,3 ;
2,2,3 .

 

A solution (DFS):

DFS is relatively easy to think of, but need pruning.

void DFS(int sum,int step,int k)

k denotes the number of points on a, this time from the beginning of the k points, sum represents by far was divided into a number, step represents a far divided the number of copies.

Since the program number is not the same, so to keep the enumeration of the number of increments (or decreasing), we can carry out repetitive pruning, record k (on how many points a), this time from the start of k points.

We also prune feasibility, as long as each enumerated from i to k i * (m - step) <= n-sum on it.

Because the next minute value smaller than the current i can not, after all is assumed that each sub-i, then if i * (m - step)> n-sum, then the remaining value is not enough points, not just the current i the line, no need to continue the DFS.

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <string>
 5 #include <math.h>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <stack>
 9 #include <queue>
10 #include <set>
11 #include <map>
12 #include <sstream>
13 const int INF=0x3f3f3f3f;
14 typedef long long LL;
15 const  int MOD = 1E9 + . 7 ;
 16  const  int MAXN = 1E4 + 10 ;
 . 17  the using  namespace STD;
 18 is  
. 19  int n-, m;
 20 is  int ANS;
 21 is  
22 is  void the DFS ( int SUM, int STEP, int K) // K represents the assigned a number, repetitive pruning 
23 is  {
 24      IF (STEP == m)
 25      {
 26 is          IF (SUM n-==) ANS ++ ;
 27          return ;
 28     }
29     for(int i=k;i*(m-step)<=n-sum;i++)//可行性剪枝 
30         DFS(sum+i,step+1,i);
31 }
32 
33 int main()
34 {
35     #ifdef DEBUG
36     freopen("sample.txt","r",stdin);
37     #endif
38     
39     scanf("%d %d",&n,&m);
40     DFS(0,0,1);
41     printf("%d\n",ans);
42     
43     return 0;
44 }

 

 

 

Solution two (DP):

DP [i] [j] denotes the integer i is divided into the number of program parts j.

First, if a get integer i, as the title of each claim is not empty, it must first come up to position number j j 1 parts are placed, then the remaining i - j number.

Then the remaining number of how to handle it? May be assigned to all of them a (dp [ij] [1]), may be assigned in duplicate (dp [ij] [2]), ..., j may be assigned to the parts (DP [ ij] [j]), each of a points all together, and that is dp [i] [j].

But this formula does not seem simple, in order to obtain a simple formula, we then seek a dp [i-1] [j-1],

 

Comparison of the above two equations can be obtained,

 

 

Two cases corresponding to the formula:

1. There are only a fraction of a 1, the remaining i-1 j-1 to be divided into parts corresponding to dp [i-1] [j -1].
2. Each value is greater than 1, i.e. in the parts of the first j in each copy to put a 1, then a ij left, then a ij which it then distributed to the j parts, corresponding to DP [ij ] [j]. (At this point I must be greater than i j)

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <string>
 5 #include <math.h>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <stack>
 9 #include <queue>
10 #include <set>
11 #include <map>
12 #include <sstream>
13 const int INF=0x3f3f3f3f;
14 typedef long long LL;
15 const int mod=1e9+7;
16 const int maxn=1e4+10;
17 using namespace std;
18 
19 int dp[205][10];
20 
21 int main()
22 {
23     #ifdef DEBUG
24     freopen("sample.txt","r",stdin);
25     #endif
26     
27     int n,m;
28     scanf("%d %d",&n,&m);
29     for(int i=1;i<=n;i++)
30     {
31         dp[i][1]=1;
32         for(int j=2;j<=m;j++)
33         {
34             if(i==j) dp[i][j]=1;
35             else if(i>j) dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
36         }
37     }
38     printf("%d\n",dp[n][m]);
39     
40     return 0;
41 }

 

 

 

 

-

Guess you like

Origin www.cnblogs.com/jiamian/p/12275461.html