题目大意:给你一个目标值和一段数字串,你要把这个串进行分割求和,让结果趋近于目标值并且不大于他
思路:搜索,每次一个x代表你要分割串的头位置,即最高位,sum代表在x位置之前分割求和的结果,k代表最优答案的位数
小结:一开始是想用一个栈保存最优答案的值,但是直接在每次搜的时候就改变这个栈了,结果最优答案可能被更替,导致一晚上没能解决这个问题,忘了还可以用一个中间数组进行存值,等到要改变最优值时再换答案。基础做法!!牢记
加上按位和的剪枝从15ms变成0ms代码
AC代码如下:
#include<cstdio>
#include<stdio.h>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
char s[10000],c;
int data[10000],n,flag,MAX,size,t,answer[10000],temp[10000];
void dfs(int x,int sum,int k)
{
if(x==n)
{
if(MAX<=sum && sum<=size)
{
if(flag && MAX<sum) //之前有重复并且此次要更新
flag=0;
else if(MAX==sum) //此次重复
flag=1;
MAX=sum;
t=k;
for(int i=0;i<t;i++)
answer[i]=temp[i];
}
return ;
}
int i,l=0;
for(i=x;i<n;i++)
{
l=l*10+data[i];
if(l>=size) break; //发现到这里已经比那个想要靠近的数来得大或者等于了 之后就不用切了
temp[k]=l;
dfs(i+1,sum+l,k+1);
}
return ;
}
int main()
{
int i,l,k;
while(~scanf("%d%s",&size,s) && (size||strcmp(s,"0")))
{
n=strlen(s);
for(MAX=i=l=flag=t=k=0;i<n;i++)
{
data[i]=s[i]-'0';
k+=data[i];
if(data[i]>=size || k>size)
{
flag=1;
break;
}
l=l*10+data[i];
}
if(flag) //剪枝,如果数中有某段数本身或者按位和大于目标就去掉
puts("error");
else if(l==size)
printf("%d %d\n",l,size);
else
{
dfs(0,0,0);
if(flag)
puts("rejected");
else
{
printf("%d",MAX);
for(i=0;i<t;i++)
printf(" %d",answer[i]);
printf("\n");
}
}
}
return 0;
}