经历了一周考试周,好久没写代码了。
题目:假设国家发行了n种不同面值的邮票,并且规定每张信封上最多只允许贴m张邮票。连续邮资问题要求对于给定的n和m的值,给出邮票面值的最佳设计,在1张信封上可贴出从邮资1开始,增量为1的最大连续邮资区间。例如,当n=5和m=4时,面值为(1,3,11,15,32)的5种邮票可以贴出邮资的最大连续邮资区间是1到70。
思路:搜索结点的状态应该是已经确定的邮票面值和它们能够贴出的最大连续邮资区间,以此来枚举下一个可能的邮票面值。x[i+1]的取值要和前面i个数各不相同,最小应该是x[i] + 1,最大就是r+1,否则r+1没有办法表示。r 表示前i个数最大连续邮资。r可以用递归+回溯来求但是时间复杂度比较高,也可以用dp优化一下。
算法作业一直没动,晚上11点才开始写的,然后就r就是直接拿递归+回溯写的,算法思路正确,时间复杂度很高。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
int m,n;
int max_r,Sum;
int temp[maxn],ans[maxn];
bool dfs1(int cur,int sum){
if(sum==Sum) return true;
if(cur>m) return false;
for(int i=1;i<=n;i++){
if(dfs1(cur+1,sum+temp[i])) return true;
}
return false;
}
void dfs(int cur){
if(cur>n){
return ;
}
int r;
//求r
for(r=temp[cur]+1;;r++){
Sum=r;
if(!dfs1(1,0)) break;
}
if(r>max_r&&cur==n){
memcpy(ans,temp,sizeof(temp));
max_r=r;
}
for(int i=temp[cur]+1;i<=r;i++){
temp[cur+1]=i;
dfs(cur+1);
temp[cur+1]=0;
}
}
int main()
{
while(cin>>n>>m){
memset(temp,0,sizeof(temp));
temp[1]=1;
max_r=0;
dfs(1);
for(int i=1;i<=n;i++){
printf("%d ",ans[i]);
}
cout<<endl;
cout<<max_r-1<<endl;
}
return 0;
}
比较仓促。。。