CQOI2009 round robin
Description
\ (n \) team competition, two teams race each time, flat \ (1 \) wins \ (3 \) negative \ (0 \) .
Given the team's final score, the number of possible points table requirements.
\ (1 \ leq n \ leq 8 \) .
Solution
Once every two race teams, apparently had conducted \ (\ frac {n \ times (n-1)} {2} \) games.
Talk about violence found:
- We enumerate all the games, and who is playing, how about the situation.
- We enumerate match each person's situation, everyone to compete with people behind him (assuming \ (3 \) person, then enumerate \ (1 \ 2 \ 1 \ 3 \ 2 \ 3 \) ) . There is a qualitative change of the algorithm, the following algorithms are improved based on the algorithm.
Let's start pruning:
Pruning math: Let wins total for the \ (the X-\) , to draw a total of \ (the y-\) , a total score for the \ (SUM \) . There \ (X \ Y + Times. 3 \ 2 = SUM Times \) , \ (X + Y = \ {n-FRAC \ Times (n-+. 1)} {2} \) . Below we got settled explain them elementary equation:
\[2 \times(x+ y) = n \times (n + 1)\]
\[n \times(n + 1) + x = sum\]
\[x = sum - n \times (n + 1)\]
\[y = \frac{\frac{n \times( n + 1)}{2} - 3 \times x} {2}\]
Obviously, we can not wins and a draw more than calculation.
Feasibility pruning: if the current people are playing to win no matter how the score is less than the required returns. Suppose the current first \ (i \) individual competition, then a maximum win \ ((n - i + 1 ) \) field.
Optimality pruning: if a man and his people behind the game is over, his score and the title given scores of different returns. If a game so that the current score is greater than a given score, then returns during the race.
Search Order pruning: We descending order of data input. Sensibility to understand it, we first calculate large, large multi-state, multi-state early on by our various pruning shears gone (without time out).
Kaka often before. The code a little, see the following data enhanced version.
HNOI2013 game
Description
\ (n \) team competition, two teams race each time, flat \ (1 \) wins \ (3 \) negative \ (0 \) .
Given the team's final score, the number of possible points table requirements.
\ (. 1 \ n-Leq \ Leq 10 \) . (Note that data range)
Solution
This question is the result of enhanced data, the original practice time out. Here to tell a magical optimization: memories of the search.
\(a \ b \ c \ d \ e \ f \ g\)
Assuming that first searched \ (d \) , we determined the \ (abcd \) of a state. The total number is now as \ (efg \) the number of programs. Obviously, \ (ABCD \) number of the program is to determine the front, then in accordance with the previous method, the number of programs back we need a recursive calculations, this is no problem, but we found that, \ (ABCD \) status may be more than a seed, we came back in the back update \ (abcd \) , we found that we were once again on the \ (defg \) search, we found \ (abcde \) is a state need \ (fg \) the number of programs.
So how state memory design? Since \ (abcd \) different states, it could lead to \ (efg \) different program number. With junior high school learned hash resolve to discrete, here unordered_map
. First before ordering the hash.
Code
#include <bits/stdc++.h>
using namespace std;
#define re register
#define F first
#define S second
typedef long long ll;
typedef pair<int, int> P;
const int N = 10 + 5, INF = 0x3f3f3f3f, Base = 28, p = 1e9 + 7;
inline int read() {
int X = 0,w = 0; char ch = 0;
while(!isdigit(ch)) {w |= ch == '-';ch = getchar();}
while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48),ch = getchar();
return w ? -X : X;
}
int n, m, sum, win, draw;
int a[N], b[N], score[N];
unordered_map <ll, int> mp;
bool cmp(int a, int b){
return a > b;
}
inline ll dfs(int x, int y){
if (score[x] + (n - y + 1) * 3 < a[x]) return 0;
if (x == n) return 1;
if (y == n + 1){
if (score[x] != a[x]) return 0;
for (int i = x + 1; i <= n; i++) b[i] = a[i] - score[i];
sort(b + x + 1, b + n + 1);
ll key = 0;
for (int i = x + 1; i <= n; i++) key = key * Base + b[i];
if (mp.find(key) != mp.end()) return mp[key];
else return mp[key] = dfs(x + 1, x + 2);
}
ll ans = 0;
if (win && score[x] + 3 <= a[x]){
score[x] += 3; win--;
ans += dfs(x, y + 1);
score[x] -= 3; win++;
}
if (draw && score[x] + 1 <= a[x] && score[y] + 1 <= a[y]){
score[x]++, score[y]++; draw--;
ans += dfs(x, y + 1);
score[x]--, score[y]--; draw++;
}
if (win && score[y] + 3 <= a[y]){
score[y] += 3; win--;
ans += dfs(x, y + 1);
score[y] -= 3; win++;
}
return ans % p;
}
int main(){
n = read();
for (int i = 1; i <= n; i++) a[i] = read(), sum += a[i];
sort(a + 1, a + n + 1, cmp);
win = sum - n * n + n;
draw = (sum - 3 * win) / 2;
printf("%lld\n", dfs(1, 2) % p);
return 0;
}