PAT 1103 Integer Factorization (30 分)深度有限搜索,关于运行超时问题 燚

The K−P factorization of a positive integer N is to write N as the sum of the P-th power of K positive integers. You are supposed to write a program to find the K−P factorization of N for any positive integers N, K and P.

Input Specification:

Each input file contains one test case which gives in a line the three positive integers N (≤400), K (≤N) and P (1<P≤7). The numbers in a line are separated by a space.

Output Specification:

For each case, if the solution exists, output in the format:

N = n[1]^P + ... n[K]^P

where n[i] (i = 1, ..., K) is the i-th factor. All the factors must be printed in non-increasing order.

Note: the solution may not be unique. For example, the 5-2 factorization of 169 has 9 solutions, such as 12​2​​+4​2​​+2​2​​+2​2​​+1​2​​, or 11​2​​+6​2​​+2​2​​+2​2​​+2​2​​, or more. You must output the one with the maximum sum of the factors. If there is a tie, the largest factor sequence must be chosen -- sequence { a​1​​,a​2​​,⋯,a​K​​ } is said to be larger than { b​1​​,b​2​​,⋯,b​K​​ } if there exists 1≤L≤K such that a​i​​=b​i​​ for i<L and a​L​​>b​L​​.

If there is no solution, simple output Impossible.

Sample Input 1:

169 5 2

Sample Output 1:

169 = 6^2 + 6^2 + 6^2 + 6^2 + 5^2

Sample Input 2:

169 167 3

Sample Output 2:

Impossible

题目大意:给定数N ,K,P 求是否有这样的K个数(可重复)使得这些数的P次方相加之和等,若有(可能有多个)则求出这样一个递减数列a,使得1≤L≤K and i<L,ai==bi  aL>bL ,否则输出“Impossible”。

思路: 1.由于此题N<=400数据量较小,且重复同一个操作,即不断的加某一个数的平方并验证是否等于N,所以可选择用深度搜索算法。(普通深度搜索会造成有一个样例超时)

            2.首先用一个数组num将平方在[0,N]之间的数存储,num[i]对应存储i的平方数。

            3.开始深搜,首先创建一个K个空间的数组temp,它用来存储每一次深搜过程中加的数i,用sum来求i的平方的和,

            4.用tempMax来存储深搜过程中所加i的总和(原因:筛选出符合题意的那个数列,即最小的数 最大那个数列),由于是从num.size()-1开始深搜,所以如果b数列的tempMax小于a数列的tempMax的话,一定有a[L]>b[L]。(如果不判断,有一个测试样例会答案错误)。

            5,如果用普通深搜,每一次都从0开始遍历,将会超时,因此可以剪枝,因为输出数列是降序,所以如果我们第层递归为第i个数,那么下一层递归就从第i个数开始,这样可以把计算量缩小一半。

坑点:1.筛选满足题意的数列,第L位最大的数列不一定位满足要求的数列,还必须满足前提a[i]==b[i] 。因此利用递减数列求和比较可以筛选出(思路的第3点)

         2.必须裁剪递归树,否则会超时(思路 第3点)。

感谢:感谢柳婼大佬的博客,让我发现自己 筛选出符合题意的数列的思维漏洞。

#include<iostream>
#include<vector>
#include<math.h>
using namespace std;
vector<int>result;
int n, k, p,Max=0;
//递归
void DFS(vector<int>&temp, vector<int>&num, int deep, int sum, int i,int tempMax) {
	//每一层加入一个数,在第K层时判断是否更新result最终数组
	if (deep == k) {
		if (sum == n && Max<tempMax) {
			result.assign(temp.begin(), temp.end());
		}
		return;
	}
	for (; i >=1; i--) {
		//递归满足的条件
		if (sum +num[i] <= n){
			temp[deep]=i;
			DFS(temp, num, deep + 1, sum + num[i], i,tempMax+num[i]);
}
	}
}
int main() {
	cin >> n >> k >> p;
	vector<int>num;
	num.push_back(0);
	//输入数列,第num[i]对应i的平方
	for (int i = 1; pow(i, p) <= n; i++) {
		num.push_back(pow(i,p));
	}
	vector<int>temp(k,0);//用来暂时存储记录的数字i
	result.resize(k,0);//最终结果数列
	DFS(temp, num, 0, 0,num.size()-1);//递归深搜
	//输出
	if (result[k-1] == 0) {
		cout << "Impossible" << endl;
	}
	else {
		printf("%d = ", n);
		for (int i = 0; i<result.size(); i++) {
			if (i != 0) printf(" + ");
			printf("%d^%d", result[i], p);
		}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值