题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1539
大意是输入n和m,把m按顺序拆分成若干个数,问这些数和的在小于n的前提下最大为多少
注意必须m的每一位都不能漏,而且要按顺序拆
比如第一个例子 拆成的各个数为1,2,34 和6,可以拆成34,346但不能是36或364,要按顺序
而他们和的最大是43
如果找不出拆法能使各个数的和小于n,输出error
如果有不止一种拆法子,输出 rejected
0 0的时候结束 m最多为六位数
这道题在杭电和北大的oj上都有,但是杭电的数据更强,链接就是杭电的
既然是按顺序拆,可以看成只是在各个位之间放空格就好了 利用深搜的思想
从m的第一位开始往后取位,取到刚大于n的前一位(还是小于n的),把取的数加上然后以这一位为起点继续取
取到的这一位做标记,最后输出的时候没有标记的位数就不要输出空格
我觉得类似于排列组合的DFS
#include<cstdio>
#include<cstring>
using namespace std;
int n,ans,a[],b[],k;
bool flag,pand[],dapand[];
void dfs(int pos,int sum,int num)
{
if (sum+num>n)
return ;
if (pos==k)
{
sum+=num;
if (sum<=n&&sum>ans)
{
ans=sum;
flag=false;
for (int i = ; i < k; i++)
dapand[i] = pand[i];
return ;
}
if (sum==ans)
flag=true;
return ;
}
dfs(pos+,sum,num*+a[pos]);//区位置
pand[pos]=true;
dfs(pos+,sum+num,a[pos]);//加和做比较
pand[pos]=false;
}
int main()
{
int m,i;
while (~scanf("%d %d",&n,&m))
{
if (n==&&m==)
break;
memset(pand,false,sizeof(pand));
ans=-;k=;
flag=true;
while (m)
{
b[k++]=m%;
m/=;
}
for (i=;i<k;i++)
a[i]=b[k-i-];
dfs(,,a[]);
if (ans==-)
{
printf("error\n");
continue;
}
if (flag)
{
printf("rejected\n");
continue;
}
printf("%d ",ans);
for (i=;i<k;i++)
{
if (dapand[i])
printf(" ");
printf("%d",a[i]);
}
printf("\n");
}
return ;
}