題意
思路:DP.這題一開始認為是dp,無奈不會表示狀態,于是一度認為是個博弈題(不知算不算博弈- -),上網一頓狂搜博弈,搜了好久也沒發現這題的簡化版之類的,不懂博弈的表示壓力很大~~。后來突然想到了一個比較笨的辦法,就是用兩個函數在那調來調去。也就是一個遞歸(發現一個函數也可以- -!)。寫出來一交TLE在第4組。又加了個記憶化,終于過了。每組數據的時間都在0.1S左右。
標稱的三種方法都很簡短,第一種還好想,后面兩種就比較難想了。
下面是標程的三種方法,哪位牛人給說下第二種的best[i][j]表示什么以及轉移方程怎么來的(不是很懂),我表示感激不盡.

標程
1
We use dynamic programming to determine, for every possible piece of board that could be left at any point in the game, how many points the best strategy gets for the winner, and how many for the loser.
2
3
Let us define best[board] to be the highest score we can hope to get by going first starting with the given board.
4
5
If we are looking at a board "a
b", the best number of points is the maximum of the following:
6
a + total[
b] - best[
b]
7
b + total[a
] - best[a
]
8
9
10
We use total[board] - best[board] as the best that we can hope to do going second starting with the given board.
11
12
If we are looking at the board "a", the best number of points is a.
13
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <string.h>
17
#include <assert.h>
18
19
#define MAXBOARD 100
20
21
int board[MAXBOARD];
22
23
/**//*
24
* best and total are indexed so that (e.g.) best[i, l] refers
25
* to the board of length l starting at place i.
26
*/
27
int total[MAXBOARD][MAXBOARD];
28
int best[MAXBOARD][MAXBOARD];
29
30
int
31
max(int a, int b)
32

{
33
return a > b ? a : b;
34
}
35
36
void
37
main(void)
38

{
39
FILE *fin, *fout;
40
int j, l, n;
41
42
fin = fopen("game1.in", "r");
43
fout = fopen("game1.out", "w");
44
assert(fin != NULL && fout != NULL);
45
46
fscanf(fin, "%d", &n);
47
for(j=0; j<n; j++)
48
fscanf(fin, "%d", &board[j]);
49
50
/**//* calculate subboard totals */
51
for(j=0; j<n; j++)
52
total[j][0] = 0;
53
54
for(l=1; l<=n; l++)
55
for(j=0; j+l<=n; j++)
56
total[j][l] = board[j] + total[j+1][l-1];
57
58
/**//* calc best for boards of size one */
59
for(j=0; j+1<=n; j++)
60
best[j][1] = board[j];
61
62
/**//* calc best for bigger boards */
63
for(l=2; l<=n; l++)
64
for(j=0; j+l<=n; j++)
65
best[j][l] = max(board[j] + total[j+1][l-1] - best[j+1][l-1],
66
board[j+l-1] + total[j ][l-1] - best[j ][l-1]);
67
68
fprintf(fout, "%d %d\n", best[0][n], total[0][n]-best[0][n]);
69
70
exit(0);
71
}
72
73
Another take on game1
74
Nick Pilkington of South Africa writes:
75
You only need O(n) space for the sum not O(n*n). This eliminates extra calculation as it can be computed during input. This also means that the board values don't need to be stored at all, leading to a much tighter solution:
76
77
#include <fstream>
78
79
using namespace std;
80
81
#define min(a,b) ((a<b)?a:b)
82
83
ifstream fin("game1.in");
84
ofstream fou("game1.out");
85
86
int n;
87
int sum[101];
88
int best[101][101];
89
90
void main()
91

{
92
fin >> n;
93
for(int i = 1; i <= n; i++)
{
94
fin >> best[i][i];
95
sum[i] = sum[i-1] + best[i][i];
96
}
97
98
for(int i = 1; i <= n; i++)
99
for(int j = 1; j+i <= n; j++)
100
best[j+i][j] = sum[j+i]-sum[j-1] - min(best[j+i-1][j], best[j+i][j+1]);
101
fou << best[n][1] << " " << sum[n] - best[n][1] << endl;
102
}
103
104
More optimizations
105
Lucian Boca Romania writes:
106
I propose some memory optimizations for "A Game" problem.
107
108
The algorithm is the same, I simulate the calculation of the matrix best[i][l] = the best score wich can be obtained by the first player with the board pieces i,i+1,
,i+l-1 (a sequence of numbers starting with position i and having the length l). I also simulate the calculation of the matrix total[i][l] = the sum of all elements in the sequence starting with position i and having the length l. The reccurence relation is:
109
110
best[i][l]=total[i][l] - min( best[i+1][l-1], best[i][l-1] )
111
112
and our goal is to obtain best[1][n]
113
The optimizations:
114
115
You don't need to memorize the board. All the information about the board is in total(i,l)
116
You don't need to use a matrix for total(i,l). You calculate a vector t[i]=the sum of elements 1,2,
,i. So, total(i,l) will be t[i+l-1] - t[i-1]
117
You don't need to use a matrix NxN, since you only need the last two columns. So, instead of using l, we can use l%2 and allocate the matrix best[NMAX][2]; the reccurence relation becomes best[i][l%2]=total(i,l) - min( best[i+1][(l-1)%2], best[i][(l-1)%2]) and our goal is to obtain best[1][n%2].
118
Here's the code:
119
#include <stdio.h>
120
#define NMAX 101
121
122
int best[NMAX][2], t[NMAX];
123
int n;
124
125
void
126
readx ()
{
127
int i, aux;
128
129
freopen ("game1.in", "r", stdin);
130
scanf ("%d", &n);
131
for (i = 1; i <= n; i++)
{
132
scanf ("%d", &aux);
133
t[i] = t[i - 1] + aux;
134
}
135
fclose (stdin);
136
}
137
138
inline int
139
min (int x, int y)
{
140
return x > y ? y : x;
141
}
142
143
void
144
solve ()
{
145
int i, l;
146
147
for (l = 1; l <= n; l++)
148
for (i = 1; i + l <= n + 1; i++)
149
best[i][l%2] = t[i + l - 1] - t[i - 1] - min (best[i + 1][(l - 1) % 2],
150
best[i][(l - 1) % 2]);
151
}
152
153
void writex ()
{
154
freopen ("game1.out", "w", stdout);
155
printf ("%d %d\n", best[1][n % 2], t[n] - best[1][n % 2]);
156
fclose (stdout);
157
}
158
159
int
160
main ()
{
161
readx ();
162
solve ();
163
writex ();
164
return 0;
165
}
166
167
思路:DP.這題一開始認為是dp,無奈不會表示狀態,于是一度認為是個博弈題(不知算不算博弈- -),上網一頓狂搜博弈,搜了好久也沒發現這題的簡化版之類的,不懂博弈的表示壓力很大~~。后來突然想到了一個比較笨的辦法,就是用兩個函數在那調來調去。也就是一個遞歸(發現一個函數也可以- -!)。寫出來一交TLE在第4組。又加了個記憶化,終于過了。每組數據的時間都在0.1S左右。
標稱的三種方法都很簡短,第一種還好想,后面兩種就比較難想了。
下面是標程的三種方法,哪位牛人給說下第二種的best[i][j]表示什么以及轉移方程怎么來的(不是很懂),我表示感激不盡.


1

2

3

4

5


6



7



8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23


24

25

26

27

28

29

30

31

32



33

34

35

36

37

38



39

40

41

42

43

44

45

46

47

48

49

50


51

52

53

54

55

56

57

58


59

60

61

62


63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91



92

93



94

95

96

97

98

99

100

101

102

103

104

105

106

107

108


109

110

111

112

113

114

115

116


117

118

119

120

121

122

123

124

125

126



127

128

129

130

131



132

133

134

135

136

137

138

139



140

141

142

143

144



145

146

147

148

149

150

151

152

153



154

155

156

157

158

159

160



161

162

163

164

165

166

167

請不要回復與文章無關的東西,謝謝