算法题——枚举

 

  基于逐个尝试答案的一种问题求解策略

 

例题1:完美立方

  http://poj.org/problem?id=1543

#include<iostream>
using namespace std;

int Triple(int a)
{
    return a*a*a;
}
int main()
{
    int N;
    int a, b, c, d;
    while (cin >> N) {
        for (a = 2; a <= N; a++) {
            for (b = 2; b < a; b++) {
                for (c = b; c < a; c++) {
                    for (d = c; d < a; d++) {
                        if (Triple(a) == (Triple(b) + Triple(c) + Triple(d))) {
                            cout << a << " " << b << " " << c << " " << d << endl;
                        }
                    }
                }
            }
        }
        cout << endl;
    }
}

  总结:即便是枚举,也是有技巧的,不要真的枚举所有的例子,有些例子是可以事先过滤掉的,这会省掉一部分时间。

 

例题2:生理周期

  http://poj.org/problem?id=1006

#include<iostream>
using namespace std;

int main()
{
    int p, e, i, d;
    while (cin >> p >> e >> i >> d) {
        int k = d;

        //找到第一个物理周期峰值的那一天
        for (++k; (k-p)%23!=0; k++);

        //找到第一个既是物理周期峰值,有事情绪周期峰值
        for ( ; (k-e)%28!=0; k+=23);  //注意跨度是物理周期时间

        //找到三个都是高峰的时间,注意跨度
        for ( ; (k-i)%33!=0; k+=(23*28));

        cout<< k-d << endl;
    }
}

  总结:注意在枚举的时候,注意跨度,可以保证很大一部分数据是不用枚举的,因为我们知道那部分数据是不满足条件的。

 

例题3:称硬币

  http://poj.org/problem?id=1013

  对于每一枚硬币先假设他是轻的,然后看测试结果和提供的结果是否符合,如果符合,那么这枚硬币就是假的,是轻的;如果不符合提供的测试结果的话,再假设这枚硬币是重的,那么在进行一次测试。

#include <iostream>
#include <cstring>
using namespace std;
char Left[3][7]; // 天平左边硬币
char Right[3][7]; // 天平右边硬币
char result[3][7]; // 结果
bool IsFake(char c,bool light) ;

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        for(int i = 0; i < 3; ++i) cin >> Left[i] >> Right[i] >> result[i];
        for(char c='A'; c<='L'; c++)
        {
            if( IsFake(c,true) )
            {
                cout << c << " is the counterfeit coin and it is light.\n";
                break;
            }
            else if( IsFake(c,false) )
            {
                cout << c << " is the counterfeit coin and it is heavy.\n";
                break;
            }
        }
    }
    return 0;
}

bool IsFake(char c,bool light)
//light  为真表示假设假币为轻,否则表示假设假币为重
{
    for(int i = 0; i < 3; ++i)
    {
        char * pLeft,*pRight; // 指向天平两边的字符串
        if(light)
        {
            pLeft = Left[i];
            pRight = Right[i];
        }
        else
        {
            pLeft = Right[i];
            pRight = Left[i];
        }
        switch(result[i][0])
        {
        case 'u':
            if ( strchr(pRight,c) == NULL)
                return false;
            break;
        case 'e':
            if( strchr(pLeft,c) || strchr(pRight,c))
                return false;
            break;
        case 'd':
            if ( strchr(pLeft,c) == NULL)
                return false;
            break;
        }
    }
    return true;
}

  总结:枚举的时候,有一种题型,可以根据自己枚举的结果和题目中给定的测试结果是否相同,如果满足条件的话,就表示枚举的值正确。

 

例题4:熄灯问题

  http://poj.org/problem?id=1222

  

 

例题

posted @ 2018-08-16 00:54  寻觅beyond  阅读(432)  评论(0)    收藏  举报
返回顶部