一些智力題的C++解法

1、在一個nxm的格子圖上塗色,你每次可以選擇一個未塗色的格子塗上你開始選定的那種顏色。同時爲了美觀,我們要求你塗色的格子不能相鄰,也就是說,不能有公共邊,現在問你,在採取最優策略的情況下,你最多能塗多少個格子?
解法:第一個格子要選相鄰格子最少的,所以應該選四個角的格子。然後向格子四個角的方向延伸直到四個方向都抵達邊界。











































class Paint {
public:
    int getMost(int n, int m) {
        if (m%2== 0)
            return (m/2)*n;
        else {
            int temp1 = (m+1)/2,temp2 = (n+1)/2;
            return temp1*temp2+(m-temp1)*(n-temp2);
        }          
    }
};


2、作爲一個馬場的主人,你要安排你的n匹賽馬和另一個馬場的n匹馬比賽。你已經知道了對方馬場的出戰表,即參加每一場的馬的強壯程度。當然你也知道你自己的所有馬的強壯程度。我們假定比賽的結果直接由馬的強壯程度決定,即更壯的馬獲勝(若相同則雙方均不算獲勝),請你設計一個策略,使你能獲得儘量多的場次的勝利。
解法: 先將兩方的馬的強壯程度由小到大排序。同時遍歷我方的馬和對方的馬,若在對方的馬中能找到強壯程度低於我方當前選中的馬,則勝局數加1,且下次不再考慮對方的這匹馬,依次進行,直到任意一方的馬被遍歷完。
class HorseRace {
public:     
    void quickSort(vector<int> &arr,int start,int end) {
        if (start > end)
            return;
        int i = start,j = end;
        int base = arr[i];
        while (i < j) {
            while (i < j && arr[j] >= base) j--;
            if (i < j) {
                arr[i] = arr[j];
                i++;
            }
            while (i < j && arr[i] <= base) i++;
            if (i < j) {
                arr[j] = arr[i];
                j--;
            }
        }
        arr[i] = base;
        quickSort(arr,start,i-1);
        quickSort(arr,i+1,end);
        return;
    }
     
    int winMost(vector<int> oppo, vector<int> horses, int n) {
        int res = 0;
        quickSort(oppo,0,n-1);
        quickSort(horses,0,n-1);
        for (int i = 0,j = 0;i < n && j < n;i++) {
            if (horses[i] > oppo[j]) {
                res++;
                j++;                                 
            }    
        }
        return res;
    }
};


3、你和你的朋友正在玩棋子跳格子的遊戲,而棋盤是一個由n個格子組成的長條,你們兩人輪流移動一顆棋子,每次可以選擇讓棋子跳1-3格,先將棋子移出棋盤的人獲得勝利。我們知道你們兩人都會採取最優策略,現在已知格子數目,並且初始時棋子在第一格由你操作。請你計算你是否能獲勝。
解法:通過列舉1、2、3、4格的情況發現,只要輪到我的時候還剩4格,我必輸無疑,因爲無論我選擇走多少格對方都可以一次走出棋盤。更巧的是,無論我走多少格,對方都可以選擇走一種格數來使這一回合湊齊4格。因此,只要總格數是4的整數倍,我就必輸無疑。而在其他任何種格數下,在走第一步的時候我都可以選擇走一種格數使得剩下的格數爲4的整數倍,這樣對方就必輸無疑。
class Jump {
public:
    int checkWin(int n) {
        if ((n-1)%4== 0)
            return 0;
        else
            return 1;
    }
};


4、A與B做遊戲。 在一個n*m的矩陣中的出發點是(1,m),終點是(n,1),規則是隻能向左移動一格,向下一格或向左下移動一格,先走到終點的爲winner。 A先走。給定兩個整數n和m,請返回最後的獲勝者的名字(A或B)。
解法:畫圖找規律,從一維推廣到二維。用1表示A勝,0表示B勝。
①當矩陣只有一行或一列時,偶數格A勝,奇數格B勝。
0
1
0
1
0
1
1





0





1





0





②其他情況時,A先走一步後的情形對應其左邊、上邊和左上方的三種情況,不同的是,不管轉移到這三種情況的哪一種,都變成了B先走。所以,A只要走到填0的那種情況,那麼B必輸。如果沒有填0的情況,則無論A怎麼走,A都會輸。
0
1
0
1
0
1
1
1




0





1





0





③按照②中的策略,把整個表格填滿。右下角的數字就代表A最終的輸贏。
0
1
0
1
0
1
1
1
1
1
1
1
0
1
0
1
0
1
1
1
1
1
1
1
0
1
0
1
0
1
(1)動態規劃的解法:
class Game {
public:
    char getWinner(int n, int m) {
        vector<vector<int> > dp(n,vector<int>(m));
        for (int i = 0;i < n;i++) {
            for (int j = 0;j < m;j++) {
                if (i == 0)
                    dp[i][j] = j%2== 0?0:1;
                else {
                    if (j == 0)
                        dp[i][j] = 1^dp[i-1][j];
                    else {
                        dp[i][j] = 1^(dp[i-1][j]&dp[i-1][j-1]&dp[i][j-1]);
                    }
                }
            }
        }
        return dp[n-1][m-1] == 1?'A':'B';
    }
};
(2)從表中找到規律,即只有當n和m都是奇數的時候B纔會贏。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章