题目大意:给你一个目标值和一段数字串,你要把这个串进行分割求和,让结果趋近于目标值并且不大于他

思路:搜索,每次一个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;
}