1 Depth First Search (DFS)

Keywords: less

September 2019 PAT - Practice Notes - 8.1

The following page numbers are labeled with the actual page number in the reader, not the self-printed page number of the book itself.

Chapter 8 Improvement (2) - Search Theme

8.1 Deep First Search (DFS)

Be careful

  1. Consider preprocessing some data to improve efficiency

Catalog

  1. A1103 Integer Factorization
  1. A1103 Integer Factorization

    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 122+42+22+22+12, or 112+62+22+22+22, 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 { a1,a2,⋯,aK } is said to be larger than { b1,b2,⋯,bK } if there exists 1≤L≤K such that ai=bi for i < L and aL > bL.

    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
    
    1. My

      #include <iostream>
      #include <cmath>
      #include <vector>
      
      using namespace std;
      
      int n = 0, k = 0, p = 0;
      int nowSum = 0;
      vector<int> factors, sequences;
      bool flag = false;
      void Find(int now, int sum)
      {
      	if (now == k) {
      		if (sum == n) {
      			if (sequences.empty()) {
      				sequences = factors;
      				for (int i = 0;i < k;++i) nowSum += factors[i];
      			}
      			else {
      				int tmp = 0;
      				for (int i = 0;i < k;++i) tmp += factors[i];
      				if (tmp > nowSum) {
      					nowSum = tmp;
      					sequences = factors;
      				}
      				else if (tmp == nowSum && factors > sequences) sequences = factors;
      			}
      			flag = true;
      		}
      		return;
      	}
      	for (;factors[now] <= factors[now - 1];++factors[now]){
      		int tmp = sum + pow(factors[now], p);
      		if (tmp <= n) Find(now + 1, tmp);
      	}
      	factors[now] = 1;
      }
      
      int main(void)
      {
      	scanf("%d %d %d", &n, &k, &p);
      	factors.resize(k, 1);
      	
      	factors[0] = pow(n - (k - 1), 1 / (float)p);
      	int end = pow((float)n / k, 1 / (float)p);
      	for (;factors[0] >= end;--factors[0]) Find(1, pow(factors[0], p));
      	if (!flag) printf("Impossible");
      	else {
      		printf("%d = %d^%d", n, sequences[0], p);
      		for (int i = 1;i < k;++i) printf(" + %d^%d", sequences[i], p);
      	}
      	
      	return 0;
      }
      

      I remember writing this for a long time...This submission goes through!Super happy!

      But my algorithm is not very good, the reference code is better written

    2. Algorithmic Notes P286

      1. "Since P is not less than 2 and fixed in a single operation, it is advisable to set up a vector fac to preprocess all NPs not exceeding N after reading P.In order to make it easier for the subscript to correspond directly to the element, 0 should also be stored here.So for N = 10, P = 2, fac[0] = 0, fac[1] = 1, fac[2] = 4, fac[3] = 9."

      2. "In order for the results to ensure that the sequence with the larger dictionary order is selected first, let the index descend from large to small so that the larger number in the fac is always selected first.

        Obviously, if you currently need to choose fac[index], then there are two choices, Select and Not Select.If you don't, you can turn the problem into a selection of fac[index - 1]...If so, since each number can be selected repeatedly, the next step should be to select fac[index]..."

      #include <cstdio>
      #include <vector>
      #include <algorithm>
      
      using namespace std;
      
      int n, k, p, maxFacSum = -1;
      vector<int> fac, ans, temp;
      
      int power(int x) 
      {
      	int ans = 1;
      	for (int i = 0;i < p;i++) ans *= x;
      	return ans;
      }
      void init()
      {
      	int i = 0, temp = 0;
      	while (temp <= n) {
      		fac.push_back(temp);
      		temp = power(++i);
      	}
      }
      void DFS (int index, int nowK, int sum, int facSum)
      {
      	if (sum == n && nowK == k) {
      		if (facSum > maxFacSum) {
      			ans = temp;
      			maxFacSum = facSum;
      		}
      		return;
      	}
      	if (sum > n || nowK > k) return;
      	if (index - 1 >= 0) {
      		temp.push_back(index);
      		DFS(index, nowK + 1, sum + fac[index], facSum + index);	// Branch of Selection
      		temp.pop_back();
      		DFS(index - 1, nowK, sum, facSum);	// Unselected Branch
      	}
      }
      
      int main()
      {
      	scanf("%d%d%d", &n, &k, &p);
      	init();
      	DFS(fac.size() - 1, 0, 0, 0);
      	if (maxFacSum == -1) printf("Impossible\n");
      	else {
      		printf("%d = %d^%d", n, ans[0], p);
      		for (int i = 1;i < ans.size();i++) printf(" + %d^%d", ans[i], p);
      	}
      	return 0;
      }
      

Posted by joshmmo on Fri, 13 Sep 2019 20:00:45 -0700