1. 程式人生 > >bzoj1306: [CQOI2009]match循環賽(模擬爆搜)

bzoj1306: [CQOI2009]match循環賽(模擬爆搜)

inpu sin log 給定 比賽 logs 明顯 數據 +=

技術分享Input第一行包含一個正整數n,隊伍的個數。第二行包含n個非負整數,即每支隊伍的得分。Output輸出僅一行,即可能的分數表數目。保證至少存在一個可能的分數表。Sample Input

6
5 6 7 7 8 8

Sample Output

121

Hint

N<=8

這個明顯就是爆搜吧,因為數據比較小。

但是數據十分神奇

枚舉每場比賽,枚舉編號較小的一隊的結果,相應的較大的也可以推出結果
當有某一隊剩下比賽全贏也比給定分數低就剪枝
當有某一隊當前比分超過給定分數也剪枝
只要你把這倆個剪枝加上,然後提交,你就會神奇的發現


為什麽還是狂T???


我還是too naive,還是被極限數據卡了。。
所以要在加一個,當這個隊伍是和最後一支隊伍比賽的時候,只要一種答案,如果和分數相差0,3,1

時就搜剩下的一個相應的狀態,相差2就剪枝
。。。我以為這個優化毫無卵用,然而TM居然是有用的。。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cmath>
 5 #include<cstring>
 6 using namespace std;
 7 
 8 const int stard[4]={3,1,0,0};
 9 
10 int a[17],b[17],n,ans;
11 
12 void dfs(int x,int y)
13 { 14 if (b[x]>a[x]) return ; 15 if (b[x]+(n-y+1)*3<a[x]) return ; 16 if (n==x) 17 { 18 ans++; 19 return; 20 } 21 if (y==n) 22 { 23 int t=a[x]-b[x]; 24 if (t==2) return; 25 b[y]+=stard[t]; 26 dfs(x+1,x+2); 27 b[y]-=stard[t];
28 } 29 else 30 { 31 b[x]+=3;dfs(x,y+1);b[x]-=3; 32 b[y]+=3;dfs(x,y+1);b[y]-=3; 33 b[x]++,b[y]++;dfs(x,y+1);b[x]--,b[y]--; 34 } 35 } 36 int main() 37 { 38 scanf("%d",&n); 39 for (int i=1;i<=n;i++) 40 scanf("%d",&a[i]); 41 dfs(1,2); 42 printf("%d",ans); 43 }

bzoj1306: [CQOI2009]match循環賽(模擬爆搜)