您的位置:首页 > 其它

深度优先搜索2-Shredding Company(算法基础 第7周)

2016-06-19 14:18 816 查看
问题描述:







分析

题目中有一点感觉题意表达不是特别清晰:就是分割数字中不能用前导0(比如0123),但是它没说是否可以理解为:0, 123。从答案来看应该是不可以这样。

刚开始做的时候算法中忽略了所有0的存在,后来发现有问题调来调去,已经懵逼了。而且在POJ上测试,这道题还没有提供测试输入、输出。先跳过吧,贴一个别人的正确答案和自己的待完善答案。

源码

正确答案来自:http://blog.csdn.net/challengerrumble/article/details/47397825

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

int num[7],tmp[7],len,mm,t,f;//num-分割方式 tmp-临时分割 len-分割组数 mm-最大分割和 f-判多解(rejected)

int getlen(int x)//求x位数对应的10^n 用以dfs时取余(分割)
{
int cnt = 1;
while(x)
{
x /= 10;
cnt *= 10;
}
return cnt/10;
}

void dfs(int rest,int sum,int site,int l,int p)//p 0无前导零 1有前导
{
if(sum + rest <=  t  && sum + rest >= mm)
{
if(sum + rest == mm || p == 1)//满足条件时多解或某组有前导零
{
f = 1;
mm = sum + rest;
return;
}
f = 0;
mm = sum + rest;
memcpy(num,tmp,sizeof(tmp));
num[site++] = rest;
len = site;
return;
}

if(sum + rest < t && sum + rest < mm) return;//当前已小 后继更小
for(int i = l; i >= 1; i /= 10)
{
tmp[site] = rest/i;
if(i > 10 && rest%i/(i/10) == 0)  dfs(rest%i, sum + rest/i, site+1, i/100,1);//判分割后余下的数是否有前导零
else dfs(rest%i, sum + rest/i, site+1, i/10,p);
}

}

int main()
{
int n;
while(~scanf("%d %d",&t,&n) && (t+n))
{
f = 0;
len = 0;
mm = -1;
dfs(n,0,0,getlen(n),0);

if(mm == -1) puts("error");
else if(f) puts("rejected");
else
{
printf("%d",mm);
for(int i = 0; i < len; ++i) printf(" %d",num[i]);
puts("");
}
}
return 0;
}


自己的待修改答案:

#include <iostream>
#include <vector>
using namespace std;

unsigned int close_tar;//距离给定目标的距离
bool objected;
vector<int> digits;
vector<int> close_digits;
unsigned int target, number;
bool pref_zero=false;//前导0

//一个数的各位数字之和
int sum_of_digits(int num) {
int sum=0;
while(num){
sum += num%10;
num /= 10;
}
return sum;
}
//大于num的最小10的幂
int maxpower_of_digits(int num) {
int power = 10;
while(num/power){
power *= 10;
}
return power;
}

//数字的长度
int len_of_num(int num) {
int len=0;
int power=10;
while(num){
len++;
num /= 10;
}
return len;
}
//从左到右计算num中'0'的索引,从1开始,反序排列
vector<int> index_zero(int num) {
int i=0;
int len_num=len_of_num(num);
int power = 10;
vector<int> index;
while(num) {
if (num%10 == 0) {
index.push_back(len_num-i);
}
num /= 10;
i++;
}
return index;
}
//添加数字中丢失的零
vector<int> addzero(const int n,vector<int> not_zero, bool& inter_zero) {
vector<int> zeroindex = index_zero(number);
if (zeroindex.empty()){
return not_zero;
}

vector<int> add_zero;
int prelen=0;
for (vector<int>::iterator i=not_zero.begin(); i<not_zero.end(); i++)
{
prelen+=len_of_num(*i);
while(prelen>=zeroindex.back()) {
add_zero.push_back(0);
inter_zero=true;//数据含有前导0
zeroindex.pop_back();
if (zeroindex.empty()){
break;
}
prelen++;
}
add_zero.push_back(*i);
}

while(!zeroindex.empty()) {
add_zero.push_back(0);
zeroindex.pop_back();
}
return add_zero;
}
void dps(int num, unsigned int tar) {
if (num==0) //数字已经用完,结束
{
//专门写段补0的程序,并判断时候有前导0
close_digits = addzero(number, digits, pref_zero);
if (tar == close_tar || pref_zero) {  //两次出现最小数或数据中间有0
objected = true;
}
else if(close_tar > tar) {
close_tar = tar;
objected = false;
}
return;
}
for (int i=1; i<maxpower_of_digits(num); i*=10) {
int pref = num/i;
int suf = num%i;
int newtar = tar-pref;
if (newtar>=0){
digits.push_back(pref);
dps(suf, newtar);
digits.pop_back();
}
}
}

int main() {
cin >> target >> number;
while(target || number) {
if (target == number){
cout << number << ' ' << number << endl;
}
else if (sum_of_digits(number) > target) {
cout << "error" << endl;
}
else {
close_tar = target;
objected = false;
pref_zero=false;
digits.clear();
close_digits.clear();

dps(number, target);

if (objected==true){
cout << "objected" << endl;
}
else {
cout << target-close_tar;
for (int i=0; i<close_digits.size(); i++) {
cout << ' ' << close_digits.at(i);
}
cout << endl;
}
}

cin >> target >> number;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: