hihoCoder搜索專題1---24點

題目鏈接:
http://hihocoder.com/problemset/problem/1304

24點規則,抽取撲克中的四張牌,每張牌使用一次的情況下進行三次加減乘除運算,考慮是否能得到24這個數。

首先是解題思路,在題目裏也有給出,這裏我自己做了歸納;

1.定義運算符 ⊙:

用於表示6種運算,在原本的加、減、乘、除的基礎上加上被減、和被除;
被減的意思是交換兩個數在減和除運算符的前後位置,比如a-b還可以有b-a這種情況。

2.兩種模式:

(((a⊙b)⊙c)⊙d) 和
((a⊙b)⊙(c⊙d));

3.複雜度計算:

4個數字全排列表示所有數字位置情況:4!=24
3個運算符⊙,每個有6種情況:6^3 = 216
兩種模式 : x2
所以:24 * 216 * 2= 10368
又因爲 a+b與a*b分別等價於b+a與b * a;
所以總情況肯定小於10368.

下面是代碼實現思路:
1.先搜索全排列,再搜索運算符。
2.搜索數字時注意標記每個數字使用一次,而每個運算可以使用多次。
3.兩種模式的計算方法(具體見代碼)

我自己照着上述思路寫了100多一點行,而在網上看到有大牛簡化寫只用了50左右,佩服,也貼在下方。

這是我自己寫的:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int num[4];
int used[4] = { 0 };
int nowNumber[4] = { 0 };
char ops[6] = { '+','-','*','/','$','&' };
char nowOps[3];
int ant = 0;
bool makeOps(int depth2);
double calc(double sum, char c, double d)
{
    if (c == '+')
        return sum + d;
    if (c == '-')
        return sum - d;
    if (c == '*')
        return sum*d;
    if (c == '/')
        return sum / d;
    if (c == '$')
        return d - sum;
    if (c == '&')
        return d / sum;
}
double calcType1(int nowNumber[], char nowOps[])
{
    double sum = nowNumber[0];
    for (int l1 = 0; l1<3; l1++)
    {
        sum = calc(sum, nowOps[l1], nowNumber[l1 + 1]);
    }
    return sum;
}
double calcType2(int nowNumber[], char nowOps[])
{
    double sum1 = nowNumber[0];
    double sum2 = nowNumber[2];
    double sum;
    sum1 = calc(sum1, nowOps[0], nowNumber[1]);
    sum2 = calc(sum2, nowOps[2], nowNumber[3]);
    sum = calc(sum1, nowOps[1], sum2);
    return sum;
}
bool makeNumber(int depth1)
{
    if (depth1 >= 4)
    {
        if (makeOps(0))
            return true;
        else return false;
    }
    for (int i = 0; i<4; i++)
    {
        if (used[i] == 0)
        {
            nowNumber[depth1] = num[i];
            used[i] = 1;
            if (makeNumber(depth1 + 1))
            {
                return true;
            }
            used[i] = 0;
        }
    }
    return false;
}
bool makeOps(int depth2)
{
    if (depth2 >= 3)
    {
        if (calcType1(nowNumber, nowOps) == 24)
        {
            //cout<<"("<<"("<<"("<<nowNumber[0]<<nowOps[0]<<nowNumber[1]<<")"<<nowOps[1]<<nowNumber[2]<<")"<<nowOps[2]<<nowNumber[3]<<")"<<endl; 
            return true;
        }
        else if (calcType2(nowNumber, nowOps) == 24)
        {
            //cout<<"("<<"("<<nowNumber[0]<<nowOps[0]<<nowNumber[1]<<")"<<nowOps[1]<<"("<<nowNumber[2]<<nowOps[2]<<nowNumber[3]<<")"<<")"<<endl;
            return true;
        }
        return false;
    }
    for (int j = 0; j<6; j++)
    {
        nowOps[depth2] = ops[j];
        if (makeOps(depth2 + 1))
        {
            return true;
        }
    }
    return false;
}
int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        memset(used, 0, sizeof(used));
        memset(nowNumber, 0, sizeof(nowNumber));
        memset(nowOps, 0, sizeof(nowOps));
        for (int w = 0; w<4; w++)
        {
            scanf("%d", &num[w]);
        }
        if(makeNumber(0))
        {
            printf("Yes\n");
        }
        else 
        {
            printf("No\n");
        }
    }
    return 0;
}

這是大牛的簡化:http://blog.csdn.net/qq_28954601/article/details/51425433

#include<stdio.h>  
#include<iostream>  
#include<algorithm>  
using namespace std;  
double a[4];  
bool flag;  
double so(double a,double b,int k)  
{  
    double s=0.0;  
    switch(k)  
    {  
        case 0:s=a+b;break;  
        case 1:s=a-b;break;  
        case 2:s=a*b;break;  
        case 3:if(b!=0)s=a/b;break;  
        case 4:s=b-a;break;  
        case 5:if(a!=0)s=b/a;break;  
    }  
    return s;  
}  
bool pan(int i,int j,int k)  
{  
    if(so(so(so(a[0],a[1],i),a[2],j),a[3],k)==24)return true;  
    if(so(so(a[0],a[1],i),so(a[2],a[3],k),j)==24)return true;  
    return false;  
}  
void solve()  
{  
    for(int i=0; i<6; i++)  
        for(int j=0; j<6; j++)  
            for(int k=0; k<6; k++)  
                if(pan(i,j,k))  
                {  
                    flag=true;  
                    return;  
                }  
}  
int main()  
{  
    int N;  
    cin>>N;  
    while(N--)  
    {  
        flag=false;  
        for(int i=0; i<4; i++)  
            cin>>a[i];  
        sort(a,a+4);  
        do  
        {  
            solve();  
            if(flag)break;  
        }  
        while(next_permutation(a,a+4));  
        if(flag)printf("Yes\n");  
        else printf("No\n");  
    }  
    return 0;  
}  
發佈了141 篇原創文章 · 獲贊 50 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章