Time Limits: 1000 ms Memory Limits: 65536 KB
Description
n支队伍打比赛,每两支队伍恰好比赛一场。平局时各得1分,而有胜负时胜者3分,负者0分。
假设三支队伍得分分别为3, 3, 3,则可能有两种情况:
队伍 A B C 得分
A - 3 0 3
B 0 - 3 3
C 3 0 - 3
队伍 A B C 得分
A - 0 3 3
B 3 - 0 3
C 0 3 - 3
给出n支队伍的最终得分(即所有比赛均已结束),统计有多少种可能的分数表。
Input
第一行包含一个正整数n,队伍的个数。第二行包含n个非负整数,即每支队伍的得分。
Output
输出仅一行,即可能的分数表数目。保证至少存在一个可能的分数表。
Sample Input
样例输入1:
3
3 3 3
样例输入2:
2
0 3
样例输入3:
3
4 1 2
样例输入4:
6
5 6 7 7 8 8
Sample Output
样例输出1:
2
样例输出2:
1 样例输出3:
1
样例输出4:
121
Data Constraint
Hint
【数据规模】
数据 1 2~3 4~6 7~12 13~19 20~25
n 3 4 5 6 7 8
题解:
深搜加剪枝,UOJ上过得了,但洛谷上过不了。DFS中的参数为正在处理的队伍和
它的对手的编号,具体剪枝为就算后面全赢也无法达到目标分数,就算后面全输
对手也无法达到目标分数,现在的分数大于目标分数,和最后一局时和目标分数
相差为2或大于三,这些情况都可以剪掉。判断本队处理完的情况,然后Ans加一,对手
处理完的情况,然后换其他的本队和其他的对手。其余情况分胜,平,负三次深搜
代码:
#include<bits/stdc++.h>
#define ipt(x) scanf("%d",&x)
#define MAXA 10000
using namespace std;
int n,target[MAXA],Ans,score[MAXA],rule[5] = {3,1,0,0};
void DFS(int me,int rival) { //team number
if(target[me] - score[me] > 3 * (n - rival + 1))
return;
if(target[rival] - score[rival] > 3 * (n - me + 1))
return;
if(score[me] > target[me] || score[rival] > target[rival])
return;
if(me == n) {
Ans++;
return;
}
if(rival == n) {
int k = target[me] - score[me];
if(k > 3 || k == 2)
return;
score[me] += k;
score[rival] += rule[k];
DFS(me + 1,me + 2);
score[me] -= k;
score[rival] -= rule[k];
return;
}
score[me] += 3;
DFS(me,rival + 1);
score[me] -= 3;
score[me]++;
score[rival]++;
DFS(me,rival + 1);
score[me]--;
score[rival]--;
score[rival] += 3;
DFS(me,rival + 1);
score[rival] -= 3;
}
int main() {
ipt(n);
for(int i=1;i<=n;i++)
ipt(target[i]);
DFS(1,2);
printf("%d",Ans);
}