bzoj1306[CQOI2009]match循环赛

bzoj1306[CQOI2009]match循环赛

题意:

n支队伍打单循环赛,赢的得3分,平局各得1分,输的不得分。已知n支队伍最终得分,求多少种可能的分数表。

题解:

爆搜,加入各种奇怪剪枝,比如:剩下的比赛全赢分数都不到要求就返回、当前分数超过了要求……还有一个重要的就是如果当前已经是最后一场就直接算出比赛结果,这个剪枝虽然表面上没什么用但实际上可以把程序从TLE的边缘拯救回来。这种题对我这种从不鸟常数的就是灾难。

代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 using namespace std;
 6 
 7 int s2[10],ans[10],tot,n,sz;
 8 void dfs(int x,int y,int z){
 9     if(z==sz){inc(i,1,n)if(s2[i]!=ans[i])return; tot++; return;}if(x>n||y>n)return;
10     if(y!=n||(y==n&&ans[x]-s2[x]==3)){
11         s2[x]+=3;
12         if(s2[x]+3*(n-y)>=ans[x]&&s2[y]+3*(n-x)>=ans[y]&&s2[x]<=ans[x]&&s2[y]<=ans[y])y==n?dfs(x+1,x+2,z+1):dfs(x,y+1,z+1);
13         s2[x]-=3;
14     }
15     if(y!=n||(y==n&&ans[x]-s2[x]==1)){
16         s2[x]++; s2[y]++;
17         if(s2[x]+3*(n-y)>=ans[x]&&s2[y]+3*(n-x)>=ans[y]&&s2[x]<=ans[x]&&s2[y]<=ans[y])y==n?dfs(x+1,x+2,z+1):dfs(x,y+1,z+1);
18         s2[x]--; s2[y]--;
19     }
20     if(ans[x]==s2[x]||y!=n){
21         s2[y]+=3;
22         if(s2[x]+3*(n-y)>=ans[x]&&s2[y]+3*(n-x)>=ans[y]&&s2[x]<=ans[x]&&s2[y]<=ans[y])y==n?dfs(x+1,x+2,z+1):dfs(x,y+1,z+1);
23         s2[y]-=3;
24     }
25 }
26 int main(){
27     scanf("%d",&n); inc(i,1,n)scanf("%d",&ans[i]);
28     memset(s2,0,sizeof(s2)); tot=0; sz=(n*n-n)>>1;
29     dfs(1,2,0); printf("%d",tot);
30 }

 

20160405

posted @ 2016-07-21 20:43  YuanZiming  阅读(364)  评论(0编辑  收藏  举报