POJ1416 Shredding Company深搜

Description

题干

 
 

Input

The input consists of several test cases, each on one line, as follows : 

tl num1 
t2 num2 
... 
tn numn 
0 0 

Each test case consists of the following two positive integers, which are separated by one space : (1) the first integer (ti above) is the target number, (2) the second integer (numi above) is the number that is on the paper to be shredded. 

Neither integers may have a 0 as the first digit, e.g., 123 is allowed but 0123 is not. You may assume that both integers are at most 6 digits in length. A line consisting of two zeros signals the end of the input. 
 

Output

For each test case in the input, the corresponding output takes one of the following three types : 

sum part1 part2 ... 
rejected 
error 

In the first type, partj and sum have the following meaning : 

1.Each partj is a number on one piece of shredded paper. The order of partj corresponds to the order of the original digits on the sheet of paper. 

2.sum is the sum of the numbers after being shredded, i.e., sum = part1 + part2 +... 

Each number should be separated by one space. 
The message error is printed if it is not possible to make any combination, and rejected if there is 
more than one possible combination. 
No extra characters including spaces are allowed at the beginning of each line, nor at the end of each line. 

Sample Input

50 12346
376 144139
927438 927438
18 3312
9 3142
25 1299
111 33333
103 862150
6 1104
0 0

Sample Output

43 1 2 34 6
283 144 139
927438 927438
18 3 3 12
error
21 1 2 9 9
rejected
103 86 2 15 0
rejected

题意:给定target和纸片上的数字num,要求碎纸机将num切为若干个数使它们的和最接近且不超过target,输出它们的和及分法。此外:

1、如果target的值等于num,则不需要切。
2、如果没有办法把纸条上的数字切成和小于target,则输出error。
3、如果有超过一种以上的切法得到最佳值,则输出rejected。

分析:深度搜索算法。对每个纸片先记录所有可能划分出的数,设置标记flag=0,。从第一位数开始进行搜索,累加各纸片切出的数,若中途其和大于target则停止当前方法,搜索到最后一位数后将当前累加和sum与已记录的结果ansSum比较,若sum>ansSum,则重新记录ansSum和ansStr,并记flag=1;若sum==ansSum,则表明此结果有多种切法,flag++。最后通过判断flag值输出结果。(若num各位之和大于target一定为error,因为这是sum最小情况)

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=6;
int T,len,ansSum,flag,pieces[maxn][maxn];
string num,ansStr;

int getVal(int s,int e)
{
	int val=0;
	for(int i=s;i<=e;i++)
	{
		val=val*10+num[i]-'0';
	}
	return val;
}

void dfs(string str,int pos,int sum)
{
	if(sum>T)//剪枝 
		return;
	if(pos==len) 
	{
		if(sum==ansSum)	//已有此解	
			flag++;
		else if(sum>ansSum)//此解更优 
		{
			flag=1;
			ansSum=sum;
			ansStr=str;			
		}
		return;
	}
	for(int i=pos;i<len;i++)
	{
		dfs(str+" "+num.substr(pos,i-pos+1),i+1,sum+pieces[pos][i]);
	}
}
void init()
{
}
int main()
{
	while(cin>>T>>num)
	{
		if(T==0&&num=="0")
			break;
		len=num.length();
		//处理纸片 
		for(int i=0;i<len;i++)
			for(int j=i;j<len;j++)
				pieces[i][j]=getVal(i,j);
			
		if(pieces[0][len-1]==T)
		{//num==T 不需切纸片 
			printf("%d %d\n",T,T);
		} 
		else
		{
			flag=0;
			ansSum=0;
			dfs("",0,0);
			if(flag>1)//最优解有多种切法 
				cout<<"rejected"<<endl;	
			else if(flag==0)//没有最优解 
				cout<<"error"<<endl;
			else 
				cout<<ansSum<<ansStr<<endl;
		}
		
	}
	return 0;
	
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值