习题:足球比赛(搜索优化)
题目描述
M中学一年一度的足球比赛开始啦,林老师作为一个热心观众,在得到消息后急急忙忙的赶到了M中学,可惜的是,当林老师赶到M中学时,所有的比赛都已经结束啦。最后林老师只得到了所有队伍的总积分表,林老师想知道,今年M中学的足球比赛一共有多少种可能的比赛情况(所有的足球队两两之间都会进行一场比赛,胜者得3分,败者得0分,打平得1分,任何两个球队之间有胜负关系不同的情况视为两种比赛情况)。
输入格式
第一行输入一个数字n(2≤n≤8)——表示M中学参加比赛的球队数量
接下来一行输入n个数字,表示每支球队得到的积分总数。题目保证至少存在一种可能的比赛情况。
输出格式
输出一个数字,表示可能的比赛情况数量。
样例
样例输入1
3
3 3 3
样例输出1
2
样例输入2
6
5 6 7 7 8 8
样例输出2
121
内存限制:64 MiB
时间限制:5000 ms
这道题的时候最开始想到的是计数DP,但是再一想,发现并不对,因为当前状态需要不止一个参数来描述,空间上可能会炸,否定DP
再一看到n的范围,发现n很小,于是就想到了搜索,但是不加优化是不可能过的,因为将整个过程看作一个图,每个球队是点,那么球队之间的比赛自然而然就是边,每一个边有三种情况,所以就是3的8*7/2次方。
考虑搜索优化,有一个优化是很容易想到的,如果当前的球队如果之后的比赛全赢,分数都达不到要求的分数,就直接退到上一层搜索。
还有一个优化就是搜索顺序的问题,如果是当前球队与之前搜索过的球队打,那么之前球队的分数就始终不确定,但是如果当前球队与未搜索的球队打,那么当前球队的分数就可以立即得出,并且再之后的搜索中不会改变,利用这一性质,如果当前球队已经确定的分数,并且不满足题意,那么也是退到上一层搜索
下面是喜闻(van)乐见的代码时间
#include<iostream>
using namespace std;
int n;
int ans;
int a[15];
int s[15];
void dfs(int now,int last)//now是当前的球队,last是上一次与哪一个球队打比赛
{
if(now==n+1)
{
ans++;
return;
}
if(last==n+1)
{
if(s[now]==a[now])
dfs(now+1,now+2);
return;
}
s[last]+=0;
s[now]+=3;
if(s[now]<=a[now]&&s[now]+(n-last)*3>=a[now])
dfs(now,last+1);
s[last]-=0;
s[now]-=3;
s[last]+=1;
s[now]+=1;
if(s[now]<=a[now]&&s[last]<=a[last]&&s[now]+(n-last)*3>=a[now]&&s[last]+(n-now-1)*3>=a[last])
dfs(now,last+1);
s[last]-=1;
s[now]-=1;
s[last]+=3;
s[now]+=0;
if(s[last]<=a[last]&&s[last]+(n-now-1)*3>=a[last])
dfs(now,last+1);
s[last]-=3;
s[now]+=0;
//三种比赛结果
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
dfs(1,2);
cout<<ans;
return 0;
}

浙公网安备 33010602011771号