http://tioj.ck.tp.edu.tw/problems/1264
怪怪規律題。給你一個棋盤,問你把某些格子塗黑,讓所有格子都符合四個相鄰的格子恰有一個被塗黑,總共有幾種方法(不可能就是0)。
完全想不通,手邊又沒有紙筆,有一天一定要買個手寫板或是搞個方便在電腦上用的計算紙…。
可以看CBD的作法,可是我看了別人的code,CBD的作法好像也不是最完整的,還有更漂亮的規律,總之決定幾個格子之後,其他格子的塗法就確定了,先亂爆搜後發現解好像只會有0,1,2,4四種。
然後,既然解這麼少種,爆搜檢個枝基本上應該會過,所以就爆搜,然後就AC了XDD。
越來越覺得與其花很多時間找規律不如先寫爆搜喇分,比賽才會高分,找證明和規律是數學家的事情,資訊就應該要爆搜嘛~~~~(不過剪枝也是要找規律啦XD)
規律大概就是,前兩格是黑的這個一定不可以是黑的、上面那一格要是不符合規定那就不用搜下去了之類的,最後要檢查最後一排有沒有符合規定。
其實看這題數字詭異的範圍(0<k<32),我覺得原題本來就是要給人爆搜的嘛~~~。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #include <bits/stdc++.h> #define F(n) Fi(i,n) #define Fi(i,n) Fl(i,0,n) #define Fl(i,l,n) for(int i=l;i<n;i++) using namespace std; const int N = 501, M = 33; int n,k,ans; bool D[N][M]; bool check(int x,int y){ if(x<0||y<0||x>=n||y>=k)return true; int tmp = 0; if(x>0)tmp += D[x-1][y]; if(y>0)tmp += D[x][y-1]; if(x<n-1)tmp += D[x+1][y]; if(y<k-1)tmp += D[x][y+1]; return tmp == 1; } int DFS(int x,int y){ if(x==n){ F(k)if(!check(x-1,i))return 0; return ans++; } if(y==k){ return DFS(x+1,0); } if(check(x-1,y))DFS(x,y+1); D[x][y] = true; if(check(x-1,y)&&(y<2||!D[x][y-2]))DFS(x,y+1); D[x][y] = false; return 0; } main(){ ios_base::sync_with_stdio(false); cin.tie(0); while(cin>>n>>k){ ans = 0; DFS(0,0); cout<<ans<<endl; } }
|