基础算法2.1——枚举法
题目上添加了超链接,大家点一下题目就会自动跳转到Poj原题界面~~ 冲鸭冲鸭ヾ(◍°∇°◍)ノ゙。
前言:
枚举法由于建模简单,所以用来提高代码实现能力十分合适,暴力搜索AC题时成就感也是满满,而且枚举法应该是之后所有算法的基础。我觉得部分算法的本质只是解决了如何枚举以及对枚举的优化。大家放心起航吧!本章节弄懂题意就可以做,所以就不添加笔记啦
poj 1006 Biorhythms
题意:已知一个人的体力、情感和智力高峰出现的时间分别是 p、e、i, 它们的周期长度分别为 23 天、28 天和 33 天,求从给定时间 d 起,下一次三个 高峰同天的时间(距离给定时间的天数),所有给定时间是非负的并且小于 365, 所求的时间小于 21252。
#include<iostream> using namespace std; int main() { int i = 1, a, b, c, start, ans; cin >> a >> b >> c >> start; while (a != -1) { for (ans = 21252;; ans--) { if (ans % 23 == a % 23 && ans % 28 == b % 28 && ans % 33 == c % 33) break; } if (ans > start) ans -= start; else ans = ans + 21252 - start; cout << "Case " << i++ << ": the next triple peak occurs in " << ans << " days." << endl; cin >> a >> b >> c >> start; } return 0; }
poj 2363 Blocks
题意:N 个边长为 1 的立方体,把它们组合成一个长方体,找出组成 最小表面积的长方体,输出它的表面积。
#include<iostream> using namespace std; int main() { int n, a, c, k, g, s; cin >> n; while (n--) { cin >> a; s = 0x3f3f3f3f; for (c = 1; c <= a; c++) { for (k = 1; k <= c; k++) { g = a / c / k; if (c * k * g == a) { s = min (s, (c * k * 2 + c * g * 2 + k * g * 2) ); } } } cout << s << endl; } return 0; }
poj 1543 Perfect Cubes
题意:求所有小于等于 N 的,完美立方数 a,使得 a^3=b^3+c^3+d^3, a、b、c、d 均为整数,N 不超过 100。
小笔记:注意遍历顺序,不要因为小问题被罚时。
#include<iostream> #include<cstdio> using namespace std; int main() { int n; scanf ("%d", &n); for (int i = 6; i <= n; i++) { for (int j = 2; j < i; j++) { for (int l = j + 1; l < i; l++) { for (int k = l + 1; k < i; k++) { if (i * i * i == j * j * j + l * l * l + k * k * k) printf ("Cube = %d, Triple = (%d,%d,%d)\n", i, j, l, k); } } } } return 0; }
poj 2586 Y2K Accounting Bug
题意: 有一个公司由于某个病毒使公司赢亏数据丢失,但该公司每月的 赢亏是一个定数,要么一个月赢利s,要么一月亏d。现在ACM只知道该公司每五个月有一个赢亏报表,而且每次报表赢利情况都为亏。在一年中这样的报表总共有8次(1到5,2到6,…,8到12),现在要编一个程序确定当赢s和亏d给出,并满足每张报表为亏的情况下,全年公司最高可赢利多少,若存在,则输出多多额,若不存在,输出"Deficit"。
小笔记:这题感觉还是挺不好理解的,再加上原题是英语的话...这才是常态
#include<iostream> using namespace std; int main() { int s, d; int res; while (cin >> s >> d) { if (d > 4 * s) res = 10 * s - 2 * d; else if (2 * d > 3 * s) res = 8 * s - 4 * d; else if (3 * d > 2 * s) res = 6 * (s - d); else if (4 * d > s) res = 3 * (s - 3 * d); else res = -1; if (res < 0) cout << "Deficit" << endl; else cout << res << endl; } return 0; }
poj 1248 Safecracker
题意:26 个大写字母分别用对应位置的数字来替换(A=1,B=2,…,Z=26), 给出 5~12 个不同的字母,从里面取 5 个,用其替换值计算,使其满足 v-w2+x3- y4+z5等于给定目标值。输出满足条件的且字典序 2最大的 5 个字母。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; bool cmp (char a, char b) { return a > b; } int main() { int n; char st[15]; int arr[15]; while (scanf ("%d %s", &n, &st) != EOF) { if (n == 0) break; int len = strlen (st); sort (st, st + len, cmp); //降序 for (int i = 0; i < len; i++) arr[i] = st[i] - 'A' + 1; int flag = 0; for (int a = 0; a < len; a++) { for (int b = 0; b < len; b++) { if (b == a) continue; for (int c = 0; c < len; c++) { if (c == a || c == b) continue; for (int d = 0; d < len; d++) { if (d == a || d == b || d == c) continue; for (int e = 0; e < len; e++) { if (e == a || e == b || e == c || e == d) continue; int v, w, x, y, z; v = arr[a], w = arr[b], x = arr[c], y = arr[d], z = arr[e]; if (v - w * w + x * x * x - y * y * y * y + z * z * z * z * z == n) { flag = 1; printf ("%c%c%c%c%c\n", st[a], st[b], st[c], st[d], st[e]); break; } } if (flag) break; } if (flag) break; } if (flag) break; } if (flag) break; } if (flag == 0) printf ("no solution\n"); } return 0; }
poj 1017 Packets
题意:工厂出售边长分别为1,2,3,4,5,6的正方形板子,但工厂只有6*6的板子,其他的板子都是从这种板子上裁剪而来的。现在给出分别这些板子的需求量,问最少需要多少块6*6的板子。
小笔记:枚举着、枚举着、就不像枚举了......这题出现策略了...
#include<cstdio> #include<cstring> using namespace std; int dir[4] = {0, 5, 3, 1};//使用下标块边长3后余下的边长2 int a[10]; int main() { int i, sum, ans; while (1) { sum = 0; for (i = 1; i <= 6; i++) { scanf ("%d", &a[i]); sum += a[i]; } if (!sum)//全为0 break; ans = a[6] + a[5] + a[4] + (a[3] + 3) / 4; //计算边长为3 4 5 6的大板子消耗量 //结余的2*2板子数 int cnt_2 = a[4] * 5 + dir[a[3] % 4]; if (a[2] > cnt_2) //当上面剩余的2*2板子量不足时,需要消耗新的板子 ans += (a[2] - cnt_2 + 8) / 9; //上面造出的1*1板子数 int cnt_1 = ans * 36 - a[6] * 36 - a[5] * 25 - a[4] * 16 - a[3] * 9 - a[2] * 4; if (a[1] > cnt_1) //当上面剩余的1*1板子量不足时,需要消耗新的板子 ans += (a[1] - cnt_1 + 35) / 36; printf ("%d\n", ans); } return 0; }