循环赛

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);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值