蓝桥杯 历届试题 带分数(搜索)
历届试题 带分数
时间限制:1.0s 内存限制:256.0MB
问题描述
100 可以表示为带分数的形式:100 = 3 + 69258 / 714。
还可以表示为:100 = 82 + 3546 / 197。
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。
输入格式
从标准输入读入一个正整数N (N<1000*1000)
输出格式
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
样例输入1
100
样例输出1
11
样例输入2
105
样例输出2
6
一道搜索题,用递归遍历所有情况。符合条件的累加计数。
一开始没思路,借鉴了网上的解答。给出链接:http://bbs.csdn.net/topics/390448276 。借鉴了12楼 nono_lonely 的代码。
我选择的做法是将N分成两部分,左边的是整数部分,右边的根据一定的规则化成分数形式。只要这个过程符合规则,则计数+1。
下面是第一次代码,与原作者代码大相径庭,但好歹AC了,调了2个小时,主要是细节问题,代码有些臃肿,后面我会再优化。
1 #include <iostream>
2 #include <string.h>
3 using namespace std;
4 int N;
5 int _count;
6 int le,ri; //左边的数,右边的数
7 int left_digits,right_digits; //左边数的位数,右边数的位数
8
9 struct CB{
10 char c; //存储字符
11 bool isu; //有没有被使用
12 }cb[10];
13
14 void flags(int n) //对该数进行标记
15 {
16 while(n){
17 int t;
18 t=n%10;
19 cb[t].isu = true;
20 n/=10;
21 }
22 }
23 void unflags(int n) //取消标记
24 {
25 while(n){
26 int t;
27 t=n%10;
28 if(t==0)
29 cb[t].isu = true;
30 else
31 cb[t].isu = false;
32 n/=10;
33 }
34 }
35 int check(int n)
36 {
37 CB cb2[10];
38 memcpy(cb2,cb,sizeof(cb));
39 while(n){
40 int t;
41 t=n%10;
42 if(cb2[t].isu || t==0){
43 return 0;
44 }
45 cb2[t].isu=true;
46 n/=10;
47 }
48 return 1;
49 }
50 int use(int n) //返回使用的位数
51 {
52 int length=0;
53 while(n){
54 length++;
55 n/=10;
56 }
57 return length;
58 }
59 bool all_use()
60 {
61 for(int i=1;i<=9;i++){
62 if(!cb[i].isu)
63 return false;
64 }
65 return true;
66 }
67 void ConstructFraction(int depth,int mol) //构造分数。depth为分子的位数,不能超过剩余位数的一半。mol为本次的分子数,如果本次能构造成功,则计数+1。
68 {
69 if(depth <= right_digits/2){
70 for(int i=mol;i<=mol*10-1;i++){
71 if(check(i)){
72 flags(i);
73 int deno = ri*i; //确定分母
74 if(check(deno)){
75 flags(deno);
76 //分母通过验证,在判断9个数字是否都用上了
77 if(all_use()){ //都用上了,计数+1
78 _count++;
79 //cout<<N<<'='<<le<<'+'<<deno<<'/'<<i<<endl;
80 }
81 unflags(deno);
82 }
83 unflags(i);
84 }
85 }
86 ConstructFraction(depth+1,mol*10);
87 }
88 }
89 int main()
90 {
91 while(cin>>N){
92 _count=0;
93 for(int i=1;i<=N-1;i++){
94 le=i;
95 ri = N-le;
96 cb[0].isu = true;
97 for(int j=1;j<=9;j++){ //初始化
98 cb[j].c = '0'+j;
99 cb[j].isu = false; //初始化时每个字符都定义为没使用
100 }
101 if(check(le)){ //核对左边的数是否符合规则
102 flags(le); //对左边的数使用过的位进行标记
103 left_digits = use(le); //返回使用的位数
104 right_digits = 9-left_digits; //剩余的位数
105 ConstructFraction(1,1);
106 unflags(le);
107 }
108 }
109 cout<<_count<<endl;
110 }
111 return 0;
112 }
Freecode : www.cnblogs.com/yym2013