蓝桥杯练习系统历届试题 带分数 dfs
Posted 小小八
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯练习系统历届试题 带分数 dfs相关的知识,希望对你有一定的参考价值。
问题描述
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
首先是暴力,TLE ,33分,讲道理我还想不到好嘛。
1 // 纯纯的暴力 挂了。 2 #include <stdio.h> 3 #include <string.h> 4 #include <iostream> 5 using namespace std; 6 7 int vis[10], visall[10]; 8 9 bool check(int num) { 10 while(num) { 11 int temp = num % 10; 12 if (vis[temp]) return false; 13 if (temp == 0) return false; 14 vis[temp]++; 15 num /= 10; 16 } 17 return true; 18 } 19 20 bool checkAll() { 21 for (int i=1; i<10; ++i) { 22 if (vis[i] != 1) return false; 23 } 24 return true; 25 } 26 27 void copyNum(int a[], int b[]) { 28 for (int i=1; i<10; ++i) { 29 a[i] = b[i]; 30 } 31 } 32 33 int main() { 34 int n; 35 while(cin >> n) { 36 memset(vis, 0, sizeof(vis)); 37 memset(visall, 0, sizeof(visall)); 38 int ans = 0; 39 40 for (int l=1; l<n; ++l) { 41 memset(vis, 0, sizeof(vis)); 42 if (!check(l)) continue; 43 copyNum(visall, vis); 44 45 for (int down=1; down<100000; ++down) { 46 int up = (n-l) * down; 47 if (down > up) continue; 48 if (up % down) continue; 49 copyNum(vis, visall); 50 if (!check(down) || !check(up)) { 51 continue; 52 } 53 if (checkAll()) { 54 //cout << l << " " << down << " " << up << endl; 55 ans++; 56 } 57 } 58 } 59 60 cout << ans << endl; 61 } 62 return 0; 63 }
然后是优化。依然感觉dfs好神奇的说。
1 /* 2 刚才暴力的优化吧。 3 先遍历左边的数字,然后dfs搜分母对应的长度 和 数字。 4 */ 5 6 #include <stdio.h> 7 #include <string.h> 8 #include <iostream> 9 using namespace std; 10 11 int lens, v, ans; 12 int vis[10], visall[10]; 13 14 bool check(int num) { 15 int k = 0; 16 while(num) { 17 int temp = num % 10; 18 if (vis[temp]) return false; 19 vis[temp]++; 20 k++; 21 num /= 10; 22 } 23 lens = 9-k; // 剩余可用数字的个数 24 return true; 25 } 26 27 void copyVis() { 28 for (int i=0; i<10; ++i) { 29 visall[i] = vis[i]; 30 } 31 } 32 33 int judge(int up) { // fenmu 34 int k = 0; 35 copyVis(); 36 while(up) { 37 int temp = up % 10; 38 if (visall[temp]) return -1; 39 visall[temp] = 1; 40 k++; 41 up /= 10; 42 } 43 return k; 44 } 45 46 void dfs(int len, int val) { // len fenzi 47 if (len > lens/2) return; 48 if (judge(v*val) == lens-len) ans++; 49 for (int i=1; i<10; ++i) { 50 if (vis[i]) continue; 51 vis[i] = 1; 52 dfs(len+1, val*10+i); 53 vis[i] = 0; 54 } 55 } 56 57 58 59 int main() { 60 int n; 61 while(cin >> n) { 62 ans = 0; 63 for (int l=1; l<n; ++l) { 64 memset(vis, 0, sizeof(vis)); 65 vis[0] = 1; 66 if (!check(l)) continue; 67 v = n - l; 68 dfs(0, 0); // len fenmu 69 } 70 cout << ans << endl; 71 } 72 return 0; 73 }
然后还有一种思路就是,对九个数字实现全排列,然后从八个空里找两个放+ 和 /。讲道理,这样的话,时间复杂度是10^6*8*7 不知道能不能过.....
以上是关于蓝桥杯练习系统历届试题 带分数 dfs的主要内容,如果未能解决你的问题,请参考以下文章