POJ 1980 DFS 剪枝
2017-08-22 00:00
169 查看
简单dfs,dfs(now,son,mother,cnt,res),其中now表示当前可以用的分母值,son和mother表示当前分数值的分子与分母,cnt表示当前分分数个数,res表示当前分数的分母乘积,注意几步剪枝
1.分母乘积大于a(等于也可能符合条件不能剪)
2.分数的个数已经大于等于n
3.当前分数值已经大于目标分数值
Code
750ms
370ms
暴力
975ms....
剪枝
47ms
减掉当前最大值也不能达到的点
1.分母乘积大于a(等于也可能符合条件不能剪)
2.分数的个数已经大于等于n
3.当前分数值已经大于目标分数值
Code
750ms
#include <stdio.h> int p, q, n, a, ans; void dfs(int now, int son, int mother, int cnt, int res){ if (p * mother == q * son && mother){ ans++; return; } if (res > a) return; if (cnt >= n) return; if (p * mother < q * son) return; int tson, tmother; if (mother) tson = son * now + mother, tmother = mother * now; else tson = 1, tmother = now; if (res * now <= a) dfs(now, tson, tmother, cnt + 1, res * now); if (res * (now + 1) <= a) dfs(now + 1, son, mother, cnt, res); } int main(){ while (~scanf("%d%d%d%d", &p, &q, &a, &n), p || q || n || a){ ans = 0; dfs(1, 0, 0, 0, 1); printf("%d\n", ans); } return 0; }
370ms
#include <iostream> using namespace std; int p, q, a, n, ans; int gcd(int x, int y){ return x % y == 0 ? y : gcd(y, x % y); } int lcm(int x, int y){ return x / gcd(x, y) * y; } void dfs(int cur, int pre, int up, int down, int product){ for (int i = pre; i * product <= a; ++i){ int k = lcm(down, i); int t1 = k / down * up; int t2 = k / q * p; if (t2 > t1 + k / i * (n - cur + 1)) return; if (t2 == t1 + k / i) ++ans; else if (t2 > t1 + k / i && cur < n) dfs(cur + 1, i, t1 + k / i, k, product * i); } } int main(){ while (scanf("%d%d%d%d", &p, &q, &a, &n) == 4){ if (p == 0 && q == 0 && a == 0 && n == 0) break; ans = 0; dfs(1, 1, 0, q, 1); printf("%d\n", ans); } return 0; }
暴力
975ms....
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #define LL long long int const MAX = 1e6 + 1; int const INF = 1 << 30; double const EPS = 0.00000001; using namespace std; int p, q, n, t, a, ans; //暴力 //cnt第几个分数,当前分母cur,当前和up/down,当前分母乘积mul void dfs(int cnt, int cur, int up, int down, int mul){ // printf("%d %d %d %d %d\n", cnt, cur, up, down, mul); if (cnt > n || mul > a || up * q > p * down) return; if (p * down == q * up){ ans++; return; } //选择当前分数 dfs(cnt + 1, cur, up * cur + down, down * cur, mul * cur); //不选当前分数 if (cur * mul <= a) dfs(cnt, cur + 1, up, down, mul); } int main(){ while (scanf("%d%d%d%d", &p, &q, &a, &n), q){ ans = 0; dfs(0, 1, 0, 1, 1); printf("%d\n", ans); } return 0; }
剪枝
47ms
减掉当前最大值也不能达到的点
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #define LL long long int const MAX = 1e6 + 1; int const INF = 1 << 30; double const EPS = 0.00000001; using namespace std; int gcd(int a, int b){ return b ? gcd(b, a % b) : a; } int p, q, n, t, a, ans; //暴力 //cnt已经选择几个分数,当前分母cur,当前和up/down,当前分母乘积mul void dfs(int cnt, int cur, int up, int down, int mul){ // printf("%d %d %d %d %d\n", cnt, cur, up, down, mul); if (cnt > n || mul > a || up * q > p * down) return; if ((q * down * (n - cnt) + up * q * cur) < p * down * cur) return; if (p * down == q * up){ ans++; return; } //选择当前分数 dfs(cnt + 1, cur, up * cur + down, down * cur, mul * cur); //不选当前分数 if (cur * mul <= a) dfs(cnt, cur + 1, up, down, mul); } int main(){ while (scanf("%d%d%d%d", &p, &q, &a, &n), q){ ans = 0; dfs(0, 1, 0, 1, 1); printf("%d\n", ans); } return 0; }
相关文章推荐
- hdoj 1455 && nyoj 293 && poj 1110 Sticks 【DFS + 剪枝 + 剪枝 + 剪枝 + 。。。+ 剪枝】
- poj 1190 生日蛋糕(dfs, 剪枝)
- poj 1564 Sum It Up | zoj 1711 | hdu 1548 (dfs + 剪枝 or 判重)
- POJ1416 DFS+剪枝
- POJ 生日蛋糕(DFS 巧妙剪枝)
- POJ 1190 生日蛋糕 DFS + 剪枝
- POJ 3172 Scales (dfs剪枝,dp超时)
- 【DFS剪枝】poj 1011 Sticks
- poj 1129 DFS 无剪枝就可AC
- POJ - 3900 The Robbery (DFS+暴力剪枝)
- POJ_2718_The smallest difference_DFS,剪枝
- POJ 3009-Curling 2.0(dfs+剪枝)
- POJ 1190 生日蛋糕(DFS+剪枝)
- [POJ 1011] Sticks DFS神剪枝
- POJ 1724 ROADS(DFS剪枝)
- poj-1011-Sticks-(dfs+剪枝)
- POJ 生日蛋糕(DFS 巧妙剪枝)
- POJ-2718 smallest difference (DFS 随机数 剪枝)
- POJ 2362 Square (DFS +剪枝)
- POJ 3009 DFS +剪枝