zoj 1003

這個題目是搜索的經典題目,深搜來找到解進而進行兩個姐相容性的判定。
#include<stdio.h>
#include<iostream>
using namespace std;

bool flag;

bool check(int big,int small,int n)
{
    int i;
    for(i=n;i>1;i--)
    {
        if(small%i==0){
            if(check(big,small/i,i-1))return true;
        }
        if(big%i==0){
            if(check(big/i,small,i-1))return true;
        }
    }

    if(small == 1){       //分數少者有可能沒有說謊
        flag = true;
    }
    else if(!flag){       //如果分少的說謊了(包含了分數多者說謊的情況)
        return true;
    }

    if(big==1&&small==1){ //兩個人的分數相容
        return true;
    }

    return false;        //得分少者的分數能被分解結束了,但是得分大不能被分解,返回上一層繼續搜索相容的情況
}

int main()
{
    int a,b;
    while(scanf("%d%d",&a,&b)!=EOF)
    {
        int big,small;

        flag = false;

        big = a>b?a:b;
        small = a>b?b:a;

        int win=big;
        if(!check(big,small,100))
        {
            win=small;
        }
        printf("%d\n",win);
    }
    return 0;
}

(1)爲什麼這樣做呢?由於情況有很多種,如果你要用數組記錄所有的可能的情況,至少得開一個100*100的二維數組,還有可能就是給出的數字很大,進行因式分解是不好處理的,應爲這個題目要求的數字絕對不能出現兩個相同數字的乘積。如果求出兩個所有可能的情況,進行比兌,但是這種思想實在不知道怎麼樣操作。一種辦法就是用nlog(n)的方法進行解的搜索。如果找到一個這兩個數的兩種可能的分解方案,就進行判定,這兩個方案是否相容,如果相容則可以得出結果;如果不相容,繼續找相容的情況了。算法的時間複雜度是(nLog(n))。這個題目需要想清楚的地方就是,如果判斷解是否相容。判斷解相容有下列幾種情況:

      1》如果小的數字到一,可以認爲小的沒有撒謊。此時要判定大的分數是否被整除到一。如果大的被整除到一,說明這種情況下,這兩個分數是相容的,判定大的贏;如果沒有被整除到一,顯然大的在說謊,此時由於不知道小的是否在說謊,所以返回上一層,再進行判斷,找有沒有跟大的分數相容的情況,如果有,就判斷大的贏,顯然這種情況是不存在的,可以直接判斷小的贏,這裏存在一個剪枝,但是在程序中沒有體現出來。

      2》如果小的數字沒到一。顯然說謊了,那麼就判定分數大的贏了;

(2)這個方法還有說明改進的地方?

(3)還有沒有其他的方法呢?

發佈了76 篇原創文章 · 獲贊 4 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章