[poj 1416]暴力dfs--我果然太菜

切碎公司
时限: 1000MS 内存限制: 10000K
提交总数: 7356 接受的: 3972
描述

您刚刚负责为碎纸公司开发新的碎纸机,尽管“正常”的碎纸机会将纸片切成小块,以使内容物变得不可读,但这种新的碎纸机需要具有以下与众不同的基本特征。

1.切碎机将目标编号和上面写有编号的纸张作为输入。

2.它将纸张切成薄片(或切成薄片),每个薄片上都有一个或多个数字。

3.写在每件作品上的数字总和是最接近目标数字的可能数字,无需进行遍历。

例如,假设目标数量为50,并且纸张的编号为12346。切碎机会将纸张切成四块,其中一块有1,另一块有2,第三块有34,第四块有6.这是因为它们的总和43(= 1 + 2 + 34 + 6)最接近所有可能组合的目标数字50而不会超过50。例如,一个组合是1、23、4和6无效,因为此组合34(= 1 + 23 + 4 + 6)的总和小于上述组合的43。12、34和6的组合也无效,因为总和52(= 12 + 34 + 6)大于目标数字50。

图1.当目标数量为50时切碎具有数字12346的纸

还有三个特殊规则:

1.如果目标编号与纸张上的编号相同,则不会裁切纸张。

例如,如果目标数量为100,并且纸张上的数量也为100,则

不会裁切纸张。

2.如果无法进行总和小于或等于目标数字的任何组合,则会在显示屏上显示错误。例如,如果目标数量为1,并且纸张上的数量为123,则不可能进行任何有效的组合,因为最小总和为1,2,3的组合。是大于目标数的6,因此会打印错误。

3.如果有多个可能的组合,总和最接近目标数字而不经过目标数字,则拒绝的信息会打印在显示屏上。例如,如果目标数量为15,并且纸张上的数量为111,则存在两种可能的组合,其最大和为12:(a)1和11以及(b)11和1;因此拒绝被打印。为了开发这样的粉碎机,您已经决定首先制作一个简单的程序来模拟上述特征和规则。给定两个数字,第一个是目标数字,第二个是要切碎的纸张上的数字,您需要弄清楚切碎机应如何“切出”第二个数字。

输入值

输入包含多个测试用例,每个测试用例都在一行上,如下所示:

tl num1
t2 num2

tn numn
0 0

每个测试用例都由以下两个正整数组成,并用一个空格分隔:(1)第一个整数(上面的ti)是目标数,(2)第二个整数(上面的numi)是要切碎的纸张上的数字。

两个整数都不能以0作为第一位数字,例如,允许123,但不允许0123。您可以假设两个整数的长度最多为6位数字。由两个零组成的线表示输入的结束。

输出量

对于输入中的每个测试用例,相应的输出采用以下三种类型之一:

和part1 part2 …
拒绝
错误

在第一种类型中,partj和sum具有以下含义:1.

每个partj是一个数字碎纸。partj的顺序与纸张上原始数字的顺序相对应。

2.sum是切碎后的数字之和,即sum = part1 + part2 + …

每个数字应以一个空格分隔。
如果无法进行任何组合,则会显示消息错误,如果存在
多个可能的组合,则拒绝该错误 。
每行的开头或每行的末尾都不允许包含空格的多余字符。
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

说说思路吧,这道题让我了解到我对dfs还是理解不够。
举例说
我们如何通过dfs穷举12346各个割位呢?看代码

#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdlib>
#include<functional>
#include<cstdio>
using namespace std;
const int maxn=1e6;
int num,a[maxn],summ,book[maxn],ans,k;
string str;
void dfs(int x,int wz,string path,int dep,int sum)
{
	if(dep==0)
	{
		if(sum<=x&&ans<=sum)
		{
		str=path;
		ans=max(ans,sum);
		book[ans]++;	
		}
		
	return;	
	}
	 
	for(int i=1;i<=dep;i++)//12346,割的话可分成6,46,346,2346,12346(我是倒着开始)
	{
		int w=wz;
		int div=1;
		int num=0;
		string temp=path;
		for(int j=0;j<i;j++)//当分为1234 6时,更新sum,与temp
		{
			num+=(w%10)*div;
			temp+=(w%10+'0');
			div*=10;
			w/=10;
		}
		temp+=' ';
		
		dfs(x,wz/div,temp,dep-i,sum+num);//更新wz(去掉之前的6,把1234搜索),割的位置的初始值也变为dep-i
		
	}
}
int main()
{
while(cin>>num>>k)	{
if(num==k&&k==0)
{
	break;
}
	str.clear();
	memset(book,0,sizeof(book));
	int rud=0,temp=k;
	while(temp)
	{
		temp/=10;
		rud++;
	}
	ans=-1;
	summ=0;
	dfs(num,k,str,rud,0);
	if(ans==-1)
	printf("error\n");
	else
	{
		if(book[ans]==1)
		{
			printf("%d",ans);
			for(int i=str.size()-1;i>=0;i--)
			{
				putchar(str[i]);
			}
		printf("\n");
		}
		else
		{
		
		printf("rejected\n");	
		}
		
	}}
	return 0;
 } 
发布了44 篇原创文章 · 获赞 4 · 访问量 1062

猜你喜欢

转载自blog.csdn.net/qq_44162236/article/details/104102287