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;
}
重复选
index+1处理通过不选择index号数进入
#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;
}
哈哈哈哈 很有成就感 这个寒假比上个暑假可以明显感觉到自己的接受能力更强了嘻嘻嘻 加油鸭!