基础算法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;
}

  

posted @ 2021-04-30 18:03  anyiya  阅读(142)  评论(0编辑  收藏  举报