题意:https://ac.nowcoder.com/acm/problem/16813

思路:

  深度搜索:每一层枚举一个面值,然后通过dp进行检查,并通过已知面值得到最多n张得到的最大表示数。

       其实,该搜索就是一个比较裸的,进行剪枝,枚举的面值还是存在范围的,上一次面值+1~n*sum(sum表示所有已知面值相加,其实这只是一个粗糙的剪枝,但是,对于我这种弱鸡莱来说还是香)

更多,细节的解释还是在代码里。还有,有多余的输出,需要自己去删除。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n, k, res, ans[], f[], curans[];
int solve(int dep, int sum){
memset(f, 0x3f, sizeof(f));
f[] = ;
for (int i = ; i <= dep; ++i){
for (int j = curans[i]; j <= n*sum; ++j) //完全背包,f[i]记录的是在已知的面值中选择最少数量
f[j] = min(f[j], f[j - curans[i]] + ); //如果最少数量大于n时,说明i这个数字不能表示,但是
} //i-1表示可表示的最大值。
for (int i = ; i <= n*sum; ++i){
if (f[i] > n){
return i - ;
}
}
return n*sum;
} void dfs(int dep, int last, int maxn, int sum){
if (dep > k){ //dep作为递归结束,maxn是一个估计上界(因为不能无限
if (res < maxn){ //枚举下去,但是面值肯定小于n*sum)
res = maxn; //而枚举的下界就是i+1
for (int i = ; i <= k; ++i){
ans[i] = curans[i];
}
}
return;
}
for (int i = last + ; i <= maxn + ; ++i){
curans[dep] = i;
int x = solve(dep, sum + i);
cout << "dep=" << dep<<endl;
cout << "maxn=" << maxn << " sum+i=" << sum + i << endl;
cout << "x=" << x << endl;
for (int i = ; i <= dep; ++i)
cout << "cur[" << i << "]="<<curans[i] << endl;
cout << endl << endl;
dfs(dep + , i, x, sum + i);
}
} int main(){
cin >> n >> k;
dfs(, , , );
for (int i = ; i <= k; ++i)
cout << ans[i] << " ";
cout << endl << "MAX=" << res << endl;
}
04-30 07:41