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