題目地址 http://poj.org/problem?id=1176
題目描述
在IOI98的節日宴會上,我們有N(10<=N<=100)盞彩色燈,他們分別從1到N被標上號碼。 這些燈都連接到四個按鈕:
按鈕1:當按下此按鈕,將改變所有的燈:本來亮著的燈就熄滅,本來是關著的燈被點亮。
按鈕2:當按下此按鈕,將改變所有奇數號的燈。
按鈕3:當按下此按鈕,將改變所有偶數號的燈。
按鈕4:當按下此按鈕,將改變所有序號是3*K+1(K>=0)的燈。例如:1,4,7…
一個計數器C記錄按鈕被按下的次數。當宴會開始,所有的燈都亮著,此時計數器C為0。
你將得到計數器C(0<=C<=10000)上的數值和經過若干操作后某些燈的狀態。寫一個程序去找出所有燈最后可能的與所給出信息相符的狀態,并且沒有重復。
輸入輸出格式
輸入格式:
不會有燈會在輸入中出現兩次。
第一行: N。
第二行: C最后顯示的數值。
第三行: 最后亮著的燈,用一個空格分開,以-1為結束。
第四行: 最后關著的燈,用一個空格分開,以-1為結束。
輸出格式:
每一行是所有燈可能的最后狀態(沒有重復)。每一行有N個字符,第1個字符表示1號燈,最后一個字符表示N號燈。0表示關閉,1表示亮著。這些行必須從小到大排列(看作是二進制數)。
如果沒有可能的狀態,則輸出一行’IMPOSSIBLE’。
輸入輸出樣例
輸入樣例#1:
10
1
-1
7 -1
輸出樣例#1:
0000000000
0101010101
0110110110
說明
在這個樣例中,有三種可能的狀態:
所有燈都關著
1,4,7,10號燈關著,2,3,5,6,8,9亮著。
1,3,5,7,9號燈關著,2, 4, 6, 8, 10亮著。
翻譯來自NOCOW
USACO 2.2
講真的這個翻譯真不咋地,之前用過別的方法做過這個題目,咱們現放開超時,優化策略,先分析這個題目,題目是給了這四種操作,讓你找到這四種操作能夠達成符合條件的類型是哪幾種,明顯搜索題,但是這里有兩個思想一定要明白,也是這道題的關鍵所在:
1.搜索上限,當搜索次數達到一定數量之后,已經搜索出所有結果,沒必要在繼續進行搜索,這個思想不僅是搜索,有時候二分也會用到這個思想。
2.重復性,結果具有規律,通過這個規律可以對某簡單結果進行擴展的到正確答案。
比如在這個題目中其實四位數足以表示所有情況,但是我為了保險還使用了6位,但是這并沒有太大的區別,考慮四位數,當對四位數變換超過6次時必然出現重復結果,雖然不知道最少變換幾次,但是6次已經夠少了。
雖然代碼寫的比較丑,比較長,但是思路明確純搜索寫法。
#include<iostream>#include<map>#include<set>#include<vector>#include<cstring>using namespace std
;set
<int> kai
;set
<int> guan
;char flag
[7];set
<string
> ob
;int n
=6,q
,cc
=-1,yy
;int op1(char *a
,char* b
);int op2(char *a
,char* b
);int op3(char *a
,char* b
);int op4(char *a
,char* b
);void dfs(char *a
,int w
){if(w
==q
){for(auto i
=kai
.begin();i
!=kai
.end();i
++){if(a
[*i
]!='1') return ;}for(auto i
=guan
.begin();i
!=guan
.end();i
++){if(a
[*i
]!='0') return ;}string temp
;temp
.clear();int t
=0;for(int i
=0;i
<yy
;i
++){temp
.push_back(a
[t
]);t
++;if(t
==6) t
=0;}ob
.insert(temp
);return;}char tem
[7];op1(a
,tem
);dfs(tem
,w
+1);op2(a
,tem
);dfs(tem
,w
+1);op3(a
,tem
);dfs(tem
,w
+1);op4(a
,tem
);dfs(tem
,w
+1);}int main(){fill(flag
,flag
+7,'1');int m
=1,x
=1,cc
=-1;cin
>>yy
>>q
;if(q
>6) q
=6;kai
.clear();guan
.clear();while(m
!=-1){cin
>>m
;if(m
==-1) break;m
=(m
-1)%6;kai
.insert(m
);}while(x
!=-1){cin
>>x
;if(x
==-1) break;x
=(x
-1)%6;guan
.insert(x
);}dfs(flag
,0);if(ob
.size()==0){cout
<<"IMPOSSIBLE"<<endl
;return 0;}for(set
<string
> ::iterator po
=ob
.begin();po
!=ob
.end();po
++)cout
<<*po
<<endl
;}int op1(char *a
,char* b
){for(int i
=0;i
<=n
;i
++){if(a
[i
]=='0') b
[i
]='1';else b
[i
]='0';}return 0;}int op2(char *a
,char* b
){for(int i
=0;i
<=n
;i
++){if(i
%2==1){if(a
[i
]=='0') b
[i
]='1';else b
[i
]='0';}else b
[i
]=a
[i
];}return 0;}int op3(char *a
,char* b
){for(int i
=0;i
<=n
;i
++){if(i
%2==0){if(a
[i
]=='0') b
[i
]='1';else b
[i
]='0';}else b
[i
]=a
[i
];}return 0;}int op4(char *a
,char* b
){for(int i
=0;i
<=n
;i
++){if(i
%3==0){if(a
[i
]=='0') b
[i
]='1';else b
[i
]='0';}else b
[i
]=a
[i
];}return 0;}
總結
以上是生活随笔為你收集整理的POJ 1176 Party Lamps USACO 2.2 派对灯(搜索)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。