一些智力题的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才会赢。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值