zoukankan      html  css  js  c++  java
  • 40-整数划分(三)

    http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=571

    整数划分(三)

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:5
     
    描述

    整数划分是一个经典的问题。请写一个程序,完成以下要求。

     

     

     
    输入
    多组输入数据。
    每组输入是两个整数n和k。(1 <= n <= 50, 1 <= k <= n)
    输出
    对于输入的 n,k;
    第一行: 将n划分成若干正整数之和的划分数。
    第二行: 将n划分成k个正整数之和的划分数。
    第三行: 将n划分成最大数不超过k的划分数。
    第四行: 将n划分成若干个 奇正整数之和的划分数。
    第五行: 将n划分成若干不同整数之和的划分数。
    第六行: 打印一个空行
    样例输入
    5 2
    样例输出
    7
    2
    3
    3
    3
    
    提示
    样例输出提示:
    1.将5划分成若干正整数之和的划分为: 5, 4+1, 3+2, 3+1+1, 2+2+1, 2+1+1+1, 1+1+1+1+1
    2.将5划分成2个正整数之和的划分为: 3+2, 4+1
    3.将5划分成最大数不超过2的划分为: 1+1+1+1+1, 1+1+1+2, 1+2+2
    4.将5划分成若干 奇正整数之和的划分为: 5, 1+1+3, 1+1+1+1+1
    5.将5划分成若干不同整数之和的划分为: 5, 1+4, 2+3
    上传者
    ACM_李如兵
    https://blog.csdn.net/lin_disguiser/article/details/50574818
    https://blog.csdn.net/ruzhuxiaogu/article/details/26749063
    只想说下多组输入!!!
    #include <iostream>
    #include <cstring>
    using namespace std;
    int dp[150][150];
    int n, k;
    
    
    int main(){
    	while(cin >> n >> k){
    		//将n划分成若干正整数之和的划分数 
    		for(int i = 0; i <= n; i++){
    			for(int j = 0; j <= n; j++){
    				if(i < j){
    					dp[i][j] = dp[i][i];
    					continue;
    				}
    				if(i == 1 || i == 0 || j == 1)
    					dp[i][j] = 1;
    				else
    					dp[i][j] = dp[i - j][j] + dp[i][j - 1];
    			}
    		}
    		int f3 = dp[n][k];
    		cout << dp[n][n] << endl;
    		memset(dp, 0, sizeof(dp));
    		
    		// 将n划分成k个正整数之和的划分数。
    		for(int i = 1; i <= n; i++){
    			for(int j = 1; j <= n; j++){
    				if(i < j){
    					dp[i][j] = 0;
    					continue;
    				}
    				if(j == 1){
    					dp[i][j] = 1;
    				}
    				else
    					dp[i][j] = dp[i - 1][j - 1] + dp[i - j][j];
    			}
    		}
    		cout << dp[n][k] << endl;
    		memset(dp, 0, sizeof(dp));
    		
    		
    		//将n划分成最大数不超过k的划分数。与第一个相同: 
    		cout << f3 << endl;
    		memset(dp, 0, sizeof(dp));
    		
    		//将n划分成若干个 奇正整数之和的划分数。
    		int ou[150][150];
    		ou[0][0] = dp[0][0] = 1;
    		for(int i = 1; i <= n; i++){
    			for(int j = 1; j <= n; j++){  //i,j必须从1开始!!! 
    				if(i < j){
    					dp[i][j] = 0;
    					continue;
    				}
    				ou[i][j] = dp[i - j][j];
    				dp[i][j] = dp[i - 1][j - 1] + ou[i - j][j];		
    			}
    		}
    		int sum = 0;
    		for(int i = 1; i <= n; i++){
    			sum += dp[n][i];	
    		}   
    		cout << sum << endl;
    		memset(dp, 0, sizeof(dp));
    		
    		//将n划分成若干不同整数之和的划分数。
    		for(int i = 0; i <= n; i++){
    			for(int j = 0; j <= n; j++){
    				if(i < j){
    					dp[i][j] = dp[i][i];
    					continue;
    				}
    				if(i == 1 && j >= 1)
    					dp[i][j] = 1;
    				else if(i == 0)
    					dp[i][j] = 1;
    				else
    					dp[i][j] = dp[i - j][j - 1] + dp[i][j - 1];
    			}
    		} 
    		cout << dp[n][n] << endl;
    	}
    	return 0;
    } 
    

      不能ac的递归代码:

    #include <iostream>
    #include <cstring> 
    using namespace std;
    int dp[105][105];
    int n, k;
    
    //将n划分成若干正整数之和的划分数 
    int fun1(int i, int j){
    	if(i < 0 || j < 0)
    		return 0;
    	if(dp[i][j])
    		return dp[i][j];
    	if(i == 0 || i == 1 || j == 1)
    		return dp[i][j] = 1;
    	return dp[i][j] = fun1(i - j, j) + fun1(i, j - 1);
    }
    
    // 将n划分成k个正整数之和的划分数。
    int fun2(int i, int j){
    	if(i < 0 || j < 0)
    		return 0;
    	if(i < j)
    		return dp[i][j] = 0;
    	if(dp[i][j])
    		return dp[i][j];
    	if(j == 1){  //注意与上面的区别 
    		return dp[i][j] = 1;
    	}	
    	return dp[i][j] = fun2(i - 1, j - 1) + fun2(i - j, j);
    }
    
    //将n划分成若干个 奇正整数之和的划分数。
    int fun3(int i, int j){
    //	if(i < 0 || j < 0)
    //		return 0;
    //	if(dp[i][j])
    //		return dp[i][j];
    //	if(i & 1 && j == 1){
    //		return dp[i][j] = 1;
    //	}
    //	return dp[i][j] = fun3(i - 1, j - 1) + fun3(i - 2 * j, j - 1);
    		int ou[150][150];
    		ou[0][0] = dp[0][0] = 1;
    		for(int i = 1; i <= n; i++){
    			for(int j = 1; j <= n; j++){  //i,j必须从1开始!!! 
    				if(i < j){
    					dp[i][j] = 0;
    					continue;
    				}
    				ou[i][j] = dp[i - j][j];
    				dp[i][j] = dp[i - 1][j - 1] + ou[i - j][j];		
    			}
    		}
    }
    
    int fun4(int i, int j){
    	if(i < 0 || j < 0)
    		return 0;
    	if(dp[i][j])
    		return dp[i][j];
    	if(i < j)
    		return dp[i][j] = fun4(i, i);
    	if(i == 1 && j >= 1)
    		return dp[i][j] = 1;
    	if(i == 0)
    		return dp[i][j] = 1;
    	return dp[i][j] = fun4(i - j, j - 1) + fun4(i, j - 1);
    }
    
    int main(){
    	while(cin >> n >> k){
    		cout << fun1(n, n) << endl;
    		memset(dp, 0, sizeof(dp));
    		cout << fun2(n, k) << endl;
    		memset(dp, 0, sizeof(dp));
    		cout << fun1(n, k) << endl;	
    		memset(dp, 0, sizeof(dp));
    		
    		int sum = 0;
    		fun3(n,n); 
    		for(int i = 1; i <= n; i++){
    			sum += dp[n][i];
    		} 
    		cout << sum << endl;
    		memset(dp, 0, sizeof(dp));
    		cout << fun4(n, n) << endl;
    	}
    	return 0;
    }
    //https://blog.csdn.net/lin_disguiser/article/details/50574818         
    

      

  • 相关阅读:
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    SVN分支
    SVN分支
    SVN 版本回退
    SVN 版本回退
    如何在excel中取消合并单元格后内容自动填充?
    如何在excel中取消合并单元格后内容自动填充?
    如何让自己像打王者荣耀一样发了疯、拼了命的学习?
  • 原文地址:https://www.cnblogs.com/zhumengdexiaobai/p/9206145.html
Copyright © 2011-2022 走看看