HDU 4023【博弈+贪心策略】

题目:Game

题意:

有如下图15种棋盘,给出每种棋盘的个数。Alice有无限个1*2形状的棋子,Bob有无限个2*1的棋子,棋子可以嵌进棋盘里,但棋子不能旋转和跨棋盘(T_T泪目啊,比赛时一队员跟我说可以跨棋盘,搞得把这题看成神题,最终仅仅浪费了时间在这题上),Alice和Bob轮流着放,Alice先放,谁最先不能嵌入棋子就输。

解题思路:

有15种,或许看起来很是繁杂。其实细心研究一下,应该能找出一些解题的策略。只有决定好选择棋盘的顺序,这题就迎刃而解了。下图是鄙人找到的顺序,首先数组的第一个元素是拿来给忽略的。A数组保存了Alice的选择顺序,B数组保存了Bob的选择顺序。按什么排序的呢?明显是按棋盘给Alice或Bob带来的益处大小来排序的。V数组保存了对应AB的顺序能给他们带来的益处大小。拿第15个棋盘来说,谁先手先就得到了这个棋盘,也就是对方不能再在这个棋盘上下棋,而且先手还能占出一个自己能下棋的稳定位置。这个棋盘是最两者最先抢的。其他棋盘分析方法类似。另外,V值等于-1表示会给对方产生一个稳定位置。

View Code
 1 #include <iostream>
2 #include <cstdio>
3 #include <string>
4 #include <cstring>
5 #include <algorithm>
6 #include <vector>
7 #include <map>
8
9 using namespace std;
10
11 const int MAX = 15 + 1;
12 int D[MAX];
13 int A[MAX] = {0, 15, 5, 6, 3, 4, 11, 12, 13, 14, 7, 8, 9, 10, 1};
14 int B[MAX] = {0, 15, 3, 4, 5, 6, 11, 12, 13, 14, 9, 10, 7, 8, 2};
15 int V[MAX] = {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 1};
16 int main()
17 {
18 freopen("in.txt","r",stdin);
19 int T;
20 scanf("%d", &T);
21 for(int t = 1; t <= T; ++t)
22 {
23 int Alice = 0, posA = 1;
24 int Bob = 0, posB = 1;
25 int turn = 1;
26 for(int i = 1; i <= 15; ++i)
27 {
28 scanf("%d", &D[i]);
29 }
30 while((posA < 15 || posB < 15) && Alice >= 0 && Bob >= 0)
31 {
32 if(turn == 1)
33 {
34 while(posA < 15 && D[A[posA]] == 0)
35 ++posA;
36 if(posA < 15)
37 {
38 --D[A[posA]];
39 if(V[posA] == -1)
40 ++Bob;
41 else
42 Alice += V[posA];
43 }
44 else
45 Alice--;
46 }
47 else
48 {
49 while(posB < 15 && D[B[posB]] == 0)
50 ++posB;
51 if(posB < 15)
52 {
53 --D[B[posB]];
54 if(V[posB] == -1)
55 ++Alice;
56 else
57 Bob += V[posB];
58 }
59 else
60 Bob--;
61 }
62 turn = !turn;
63 }
64 while(Alice >=0 && Bob >= 0)
65 {
66 if(turn == 1)
67 --Alice;
68 else
69 --Bob;
70 turn = !turn;
71 }
72 printf("Case #%d: ", t);
73 printf(Alice >= 0? "Alice" : "Bob");
74 printf("\n");
75 }
76 return 0;
77 }
posted on 2011-09-26 16:41  Kenfly  阅读(517)  评论(1编辑  收藏  举报