题意:有一个最多六位数字的纸条,放在碎纸机上去粉碎,每次可以仍以切割任意数字下来,比如12345,在1,2,3,4,5之间的空挡都可以去切一刀,然后会得到几个数字,然后对这些数字取和,然后输出不大于所给目标数字的最大数字。例如第一个例子50 12346,50>1+2+34+6=43,如果有多个解输出rejected,如果没有解输出error,如果有解那么输出最大数字,并且输出所有碎片。
想法:一共最多六个数字,那么就有五个空挡可以选择切还是不切,所以深搜每一种情况,然后纪录所有被切割的数字,可以适当加一点剪枝:如果当前要增加的碎片上的数加上已经加上的数大于目标数,那就没有必要继续了。
#include<stdio.h> int target_num,num; int cuted_num[7]; int ans_num[7]; int best_ans; int num_of_best_ans; int ans_cnt; int Ans_num[7]; int cul(int x) { if(x == 0) return 1; if(x == 1) return 10; if(x == 2) return 100; if(x == 3) return 1000; if(x == 4) return 10000; if(x == 5) return 100000; if(x == 6) return 1000000; } void dfs(int cur_num, int len, int up_index, int down_index, int cnt) { if(cur_num > target_num) return; if(down_index == len + 1){ if(cur_num > best_ans){ best_ans = cur_num; ans_cnt = cnt - 1; num_of_best_ans = 1; for(int i = 1; i <= ans_cnt; ++i){ Ans_num[i] = ans_num[i]; } } else if(cur_num == best_ans){ num_of_best_ans = 2; } return; } int add_num = 0; int EXP = 0; for(int i = down_index; i >= up_index; --i){ add_num += cuted_num[i] * cul(EXP); EXP++; } if(add_num + cur_num <= target_num){ ans_num[cnt] = add_num; if(down_index == len){ dfs(cur_num + add_num, len, down_index + 1, down_index + 1, cnt + 1); } else{ dfs(cur_num + add_num, len, down_index + 1, down_index + 1, cnt + 1); dfs(cur_num, len, up_index, down_index + 1, cnt); } } } int main() { while(~scanf("%d%d", &target_num, &num)){ if(target_num == 0 && num == 0) break; if(target_num == num){ printf("%d %d\n", target_num, num); continue; } int temp_num[7]; int pos = 0,len; while(num){ temp_num[++pos] = num % 10; num /= 10; } len = pos; for(int i = 1;i <= len; ++i){ cuted_num[i] = temp_num[pos--]; } num_of_best_ans = 0; best_ans = -1; dfs(0,len,1,1,1); if(num_of_best_ans > 1) printf("rejected\n"); else if(num_of_best_ans == 1){ printf("%d", best_ans); for(int i = 1; i <= ans_cnt; ++i){ printf(" %d", Ans_num[i]); } printf("\n"); } else printf("error\n"); } return 0; }