题意:
要求碎纸机能够把纸条上的数字切成一些片段,这些片段的和最接近而不超过所给的值tar,第一个样例,tar的值是50,而纸条上的数字是12346,应该把数字切成四部分,分别是1、2、34、6。因为这样所得到的和43 (= 1 + 2 + 34 + 6) 是所有可能中最接近而不超过50的。
三个要点:
1、如果tar的值等于纸条上的值,则不切。
2、如果没有办法把纸条上的数字切成小于target,则输出error。如target是3而纸条上的数字是333。
3、如果有超过一种以上的切法得到最佳值,则输出rejected。如target为37,纸条上的数字是333,则有以下两种切法33、3或者3、33.
枚举分割点,判断就行了,唯一的知识就是写个枚举分割点的dfs;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<climits>
#include<list>
#include<stack>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
int tar;
int point[10];
int len;
string str;
struct node
{
int ans;
int arr_num;
int reject;
string arr[10];
}fin;
node add(int m)
{
point[m+1]=len;
int i;
int temp_ans=0;
node now;
now.reject=0;
for(i=0;i<=m;++i)
{
string temp=str.substr(point[i],point[i+1]-point[i]);
now.arr[i]=temp;
int j;
int sub_len=temp.size();
int base=1;
int sub_ans=0;
for(j=sub_len-1;j>=0;--j)
{
sub_ans+=(base*(temp[j]-'0'));
base*=10;
}
temp_ans+=sub_ans;
}
now.arr_num=m;
now.ans=temp_ans;
return now;
}
void dp_group(int m,int mmax,int start)
{
if(m==mmax)
{
node t=add(m);
if(t.ans<=tar)
{
if(t.ans==fin.ans)
{
fin.reject=1;
return ;
}
else
{
if(fin.ans>tar)
{
fin=t;
}
else
{
fin=t.ans>fin.ans?t:fin;
}
}
}
return ;
}
int i;
for(i=start+1;i<len;++i)
{
point[m+1]=i;
dp_group(m+1,mmax,i);
}
}
int main()
{
char st[10];
while(scanf("%d%s",&tar,st),tar!=0)
{
int i;
str=st;
len=str.size();
fin.ans=INT_MAX;
fin.reject=0;
mem(point);
for(i=0;i<len;++i)
{
dp_group(0,i,0);
}
if(fin.ans==INT_MAX)
{
cout<<"error"<<endl;
}
else if(fin.reject)
{
printf("rejected\n");
}
else
{
printf("%d ",fin.ans);
for(i=0;i<fin.arr_num;++i)
{
cout<<fin.arr[i]<<" ";
}
cout<<fin.arr[i]<<"\n";
}
}
}