計算24點

題目參考鏈接:杭電1427   http://acm.hdu.edu.cn/showproblem.php?pid=1427

在自行編寫的暴力枚舉代碼TLE之後,在網上搜索了一下,得到如下簡化後的暴力求解思路。

先將給你的4個數進行全排列,在這過程中,對每一個全排列去進行判斷,看這種排列是否能用四則運算算出24點。若算出24點,便輸出“Yes”。對於其中某一種排列a,b,c,d,設#爲任意一種四則運算,則僅需討論以下兩種情況,即考慮了所有可能的運算結果。
1. (a#b)#(c#d)
2. ((a#b)#c)#d
注意:在這種簡化的情形下,-24也是可以的。可參考:鏈接一:代碼參考鏈接二:思路簡化鏈接三:考慮-24。而在鏈接四:簡短代碼版中,作者通過algorithm裏的next_permutation枚舉給定數組的所有排列,從而大大簡化了代碼。
其中next_permutation的用法參見C++文檔,有關其實現的討論參見stackoverflow的討論

整合上述信息,在杭電1427上AC的參考代碼如下:

#include <iostream>
using namespace std;
 
const int INF = 1 << 30;
 
int a[4];
int res[4];
bool vis[4];
bool flag;
 
 
int deal(int x,int y,int i)  //四則運算
{
    switch(i)
    {
    case 0 : return x + y;
    case 1 : return x - y;
    case 2 : return x * y;
    case 3 : if(y != 0 && x % y == 0) return x / y;else return INF;
    }
}
 
bool can()        //判斷該種排列運用四則運算是否能算出
{
    int i,j,k;
    int t1,t2,t3;
    for(i = 0;i < 4;i ++)         //(a @ b) @ (c @ d)
    {
        t1 = deal(res[0],res[1],i);
        if(t1 == INF) continue;
        for(j = 0;j < 4;j ++)
        {
            t2 = deal(res[2],res[3],j);
            if(t2 == INF) continue;
            for(k = 0;k < 4;k ++)
            {
                t3 = deal(t1,t2,k);
                if(t3 == 24 || t3 == -24) return 1;
            }
        }
    }
    for(i = 0;i < 4;i ++)     //((a @ b) @ c) @ d
    {
        t1 = deal(res[0],res[1],i);
        if(t1 == INF) continue;
        for(j = 0;j < 4;j ++)
        {
            t2 = deal(t1,res[2],j);
            if(t2 == INF) continue;
            for(k = 0;k < 4;k ++)
            {
                t3 = deal(t2,res[3],k);
                if(t3 == 24 || t3 == -24) return 1;
            }
        }
    }
    return 0;    //都不能算出,說明無解
}
 
void dfs(int p)    //全排列
{
    if(p == 4)
    {
        if(can()) flag = 1;
        return;
    }
    int i,j;
    for(i = 0;i < 4;i ++)
    {
        if(!vis[i]) 
        {
            res[p] = a[i];
            vis[i] = 1;
            dfs(p + 1);
            if(flag) return;
            vis[i] = 0;
        }
    }
}
 
int main()
{
    char s[3];
    int i,j,k;
    while(1)
    {
        for(i = 0;i < 4;i ++)
        {
            if(scanf("%s",s) == EOF) return 0;
            if(s[0] == 'A') a[i] = 1;
            else if(s[0] == 'J') a[i] = 11;
            else if(s[0] == 'Q') a[i] = 12;
            else if(s[0] == 'K') a[i] = 13;
            else if(s[0] == '1' && s[1] == '0') a[i] = 10; 
            else a[i] = s[0] - '0';
        }
        flag = 0;
        memset(vis,0,sizeof(vis));
        dfs(0);
        if(flag) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章