PAT演習
169 5 2
出力:
169 = 6^2 + 6^2 + 6^2 + 6^2 + 5^2
問題を脇に置いて本質を見ると、それは実際には単純で繰り返し可能な選択問題です。DFSは古い古典的な問題です。恐れることはありません!
注意点:
1。nを超えない数を前処理します。次のテーブルとデータの一貫性を保つために、配列を使用して0を格納および格納
します。2。fac配列を逆方向に処理して、次のことを行う必要がないようにします。要因の順序を考慮してください
。ACコード
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100010;
int n, k, p, maxSum = -1;
vector<int> fac, ans, temp;
int pow(int i)
{
int sum =1;
for(int j = 0; j < p; j++)
{
sum *= i;
}
return sum;
}
//预处理 把不超过n的数字提前存放进去
void init()
{
int i = 0, temp = 0;
while(temp <= n)
{
fac.push_back(temp);
temp = pow(++i);
}
}
int num;
int flag[maxn];
//int Facsum因子平方和 int sum因子和
void DFS(int index, int nowk, int Facsum, int sum)
{
if(index == 0 || nowk > k || Facsum > n) return;//不选fac[0]
// if(nowk > k || Facsum > n) return;
if(nowk == k && Facsum == n)
{
if(sum > maxSum)
{
maxSum = sum;
ans = temp;
}
return;
}
//可重复选择当前的 但是不加入temp
temp.push_back(index);
DFS(index,nowk + 1,Facsum + fac[index], sum + index);
temp.pop_back();
//不选index号数
DFS(index - 1, nowk, Facsum, sum);
}
int main()
{
cin >> n >> k >> p;
init();
DFS(fac.size()-1,0,0,0);
if(maxSum == -1) cout << "Impossible";
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;
}
BFSの古典的な例の補足
バックパック問題
#include <cstdio>
#include <iostream>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100010;
//背包问题
int n, v, maxvalue = 0;//n件商品 最大价值
int w[maxn],c[maxn];
//void DFS(int index,int sumw, int sumc)
// {
// if(n == index)
// {
// if(sumw <= v && sumc > maxvalue)
// {
// maxvalue = sumc;
// }
// return ;
// }
// DFS(index + 1, sumw, sumc);
// DFS(index + 1, sumw + w[index], sumc + c[index]);
// }
//剪枝
void DFS(int index,int sumw, int sumc)
{
if(n == index) return ;
DFS(index + 1, sumw, sumc);
if(sumw + w[index]<= v)
{
if(sumc + c[index] > maxvalue)
maxvalue = sumc + c[index];
}
DFS(index + 1, sumw + w[index], sumc + c[index]); //选index
}
int main()
{
cin >> n >> v;
for(int i = 0; i < n; i++)
{
cin >> w[i];
}
for(int i = 0; i < n; i++)
{
cin >> c[i];
}
DFS(0, 0, 0);
cout << maxvalue;
return 0;
}
番号を選択してください
繰り返さないでください
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100010;
//从n中选择k个数 满足k个数之和为x并且平方和最大
vector<int> temp,ans;
int n,k,x;
int A[maxn], maxsumseq = -1;
void DFS(int index, int nowk,int sum, int sumseq)
{
if(nowk == k && sum == x)
{
if(sumseq > maxsumseq)
{
maxsumseq = sumseq;
ans = temp;
}
return;
}
if(index > n||nowk > k|| sum > x) return;
temp.push_back(A[index]);
DFS(index + 1,nowk + 1,sum + A[index], sumseq + A[index] * A[index]);
temp.pop_back();
DFS(index + 1,nowk,sum,sumseq);
}
int main()
{
cin >> n >> k >> x;
for(int i = 0; i < n; i++)
{
cin >> A[i];
}
DFS(0, 0, 0,0);
for(vector<int>::iterator it = ans.begin(); it != ans.end(); it++)
{
cout << *it << " ";
}
return 0;
}
繰り返し選択
インデックス番号を選択しないことでインデックス+1処理に入ります
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100010;
//从n中可重复选择k个数 满足k个数之和为x
vector<int> temp,ans;
int n,k,x;
int A[maxn], maxsumseq = -1;
void DFS(int index, int nowk,int sum, int sumseq)
{
if(nowk == k && sum == x)
{
if(sumseq > maxsumseq)
{
maxsumseq = sumseq;
ans = temp;
}
return;
}
if(index > n||nowk > k|| sum > x) return;
temp.push_back(A[index]);
DFS(index, nowk + 1,sum + A[index], sumseq + A[index] * A[index]);
temp.pop_back();
DFS(index + 1,nowk,sum,sumseq);
}
int main()
{
cin >> n >> k >> x;
for(int i = 0; i < n; i++)
{
cin >> A[i];
}
DFS(0, 0, 0,0);
for(vector<int>::iterator it = ans.begin(); it != ans.end(); it++)
{
cout << *it << " ";
}
return 0;
}
ははははは、達成感があります。この冬休みは、去年の夏よりも受け入れやすいと感じます。へへへさあ!