先补充一点小知识,看到下面的知识写的很好:
分治法的基本思想:将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些问题,然后将各个子问题的解合并成原问题的解。
分治法所能解决的问题一般具有以下几个特征:
该问题的规模缩小到一定的程度就可以容易地解决;因为问题的计算复杂性一般是随着问题规模的增加而增加,因此大部分问题满足这个特征。
该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质这条特征是应用分治法的前提,它也是大多数问题可以满足的,此特征反映了递归思想的应用
利用该问题分解出的子问题的解可以合并为该问题的解;能否利用分治法完全取决于问题是否具有这条特征,如果具备了前两条特征,而不具备第三条特征,则可以考虑贪心算法或动态规划。
该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。这条特征涉及到分治法的效率,如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然也可用分治法,但一般用动态规划较好(例如记忆化搜索是分治转化为动归的一个经典)。
“Well, it seems the first problem is too easy. I will let you know how foolish you are later.” feng5166 says.
“The second problem is, given an positive integer N, we define an equation like this:
N=a[1]+a[2]+a[3]+…+a[m];
a[i]>0,1<=m<=N;
My question is how many different equations you can find for a given N.
For example, assume N is 4, we can find:
4 = 4;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;
so the result is 5 when N is 4. Note that “4 = 3 + 1” and “4 = 1 + 3” is the same in this problem. Now, you do it!”
Input
The input contains several test cases. Each test case contains a positive integer N(1<=N<=120) which is mentioned above. The input is terminated by the end of file.
Output
For each test case, you have to output a line contains an integer P which indicate the different equations you have found.
Sample Input
4
10
20
Sample Output
5
42
627
故事还是那个故事,第一个问题人家答出来了还不能接公主走,还要答第二个,魔兽就是魔兽啊!
这次问题高级太多了,整数划分问题。输入第一行是整数,输出是这个整数有多少划分。
上来啥也不说一通递归 如下 ↓
#include <iostream>
using namespace std;
int spilt(int n,int m){
if(n==1||m==1)
return 1;
else if(n<m)
return spilt(n,n);
else if(n==m)
return spilt(n,m-1)+1;
else
return spilt(n,m-1)+spilt(n-m,m);
}
int main(){
int n;
while(cin>>n){
cout<<spilt(n,n)<<endl;
}
return 0;
}
所谓分治,分而治之。这个函数有两个变量,n是我们所求,m是小于n的数。n是我们所求,m代表最大加数不大于m的划分数。什么意思呢?举例来说,n是4,即求4的整数划分时,m可在递归过程中依次取4,3,2,1。当然了,如果m大于n,递归时会将m变为n。下面依次看递归条件:
①n等于1时划分数自然只有1,而m=1是递归的边界条件,即已经到了不大于1的加数的划分,自然也只有一个;
②n<m时将m变为n;
③n等于m时,自然只有一个是本身,所以先加上1,然后m-1遍历;
④n>m>1时,要加上m的整数划分,和m-1的整数划分。
很好,变得很简洁。但!
超时了!哎呀怎么超时了呢……递归时间复杂度太高了
所以搜索了一下用动态规划……并且,用cin cout还re了,要用scanf printf。
#include<iostream>
using namespace std;
int dp[121][121];
int solve(int n){
for(int i=1;i<=n;i++)
dp[0][i]=1;
for (int i=1;i<=n;i++){
dp[i][0]=0;
for(int j=1;j<=n;j++){
if(i<j)
dp[i][j]=dp[i][i];
else
dp[i][j]=(dp[i-j][j]+dp[i][j-1]);
}
}
return dp[n][n];
}
int main() {
int n,ans;
while(cin>>n){
cout<<solve(n)<<endl;
}
return 0;
}
用二维数组来存,把