2022.02.21 带分数(dfs全排列+暴力搜索)
题目复盘
100 可以表示为带分数的形式:100 = 3 + 69258 / 714。
还可以表示为:100 = 82 + 3546 / 197。
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。
输入
从标准输入读入一个正整数N (N< 1000*1000)
输出
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
样例输入
100
样例输出
11
思路复盘
首先搞清楚题目要我们做什么,也就是审题,我们需要填入三个未知量,分别是整数、分子、分母。其中每个未知量其中的数字只能出现一次而且1-9全要出现,然后还要满足上述带分数等式。
考虑暴力搜索,但暴力搜索,不单单随便几个for循环就能解决问题的,马克思主义中国化也是需要不断改造才能符合国情,这里也是一样,我们可以发现,整数部分的位数一定要小于7才行,否则分子分母没有数字可填,事实上读者可以将此题当作一个填数字游戏,每个数字卡片只能用一次,这放在我们计算机编程上可以用什么存储结构??最简单的当然是数组。
但是卡片怎么填呢??我们可以把所有的卡片分成三段,分别代表整数、分子、分母,然后逐个位数搜索过去,然后判断了就行了是不是?对的,就是这样的一个思路,然后我们把卡片全排列一下,就可以列举出所有的情况了。
全排列用dfs和剪枝的思想比较快,有兴趣的读者可以参阅之前的dfs博客,这里不再赘述了。
直接看代码把
#include<iostream>
using namespace std;
int n,ans;
int pailie[10],vis[10];
int get_num(int start,int end)
{
int res=0; //result 考虑如果不写‘=0’会怎么样,本人死在这里
for(int i=start;i<=end;i++) res=res*10+pailie[i];
return res;
}
void baoli(int pailie[])
{
//整数部分最多为7位,否则剩下两位就没数字了.
int zs,fz,fm; //整数,分子,分母
for(int i=1;i<=7;i++)
{
zs=get_num(1,i);
for(int j=i+(9-i)/2;j<=9;j++){
int fz=get_num(i+1,j-1); //分子必须留一位给分母
int fm=get_num(j,9);
if(zs+fz/fm==n&&(fz%fm)==0) ans++;
}
}
}
void dfs(int h)
//全排列
{
if(h==10)
{
baoli(pailie);
}
else
{
for(int i=1;i<=9;i++)
{
if(vis[i]==0)
{
vis[i]=1;
pailie[h]=i;
dfs(h+1);
vis[i]=0;
}
}
}
}
int main()
{
cin>>n;
dfs(1);
cout<<ans<<endl;
return 0;
}
end...关注后续更新~