1. 程式人生 > >BZOJ1080 暴力+位移運算符的用法

BZOJ1080 暴力+位移運算符的用法

pan def while 字符 運算符 zoj function str limit

1080: [SCOI2008]劣質編碼

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 337 Solved: 148
[Submit][Status][Discuss]

Description

  一個編碼方案把每個字符對應到一個01串。例如{1,1010,01,10101}就是一個編碼方案,它把四個字符(假設
它們為a,b,c,d)分別對應到串1、1010,01,10101。字符串的編碼為各字符編碼的連接。例如,在剛才的編碼方
案中,字符串cac的編碼為01101,dcb的編碼為10101011010。 進一步分析發現,剛才的編碼是相當劣質的,因為
字符串ba, acc和d的編碼都是10101。對於一個編碼方案,你的任務是找出三個不同的字符串,使得它們的編碼全
相同。換句話說,找一個01編碼串,使得它至少有三種解碼方式。如果有多組解,這個編碼串應當盡量短。

Input

  第一行包含一個整數n,即符號的個數。以下n行每行為一個長度不超過50的01串(可能為空串),即各符號的
編碼。

Output

  僅一行,包含一個整數,即最短編碼的長度。如果無解,輸出-1。

Sample Input

4
1
1010
01
10101

Sample Output

5
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<string>
#include<map>
using namespace std;
typedef vector<int> ve;
map<ve,int>hash;
queue<ve>Q;
string s[35];
int n;
void work(){
ve u,v,t;
for(int i=1;i<=n;++i)
if(s[i]=="") {puts("0");exit(0);}
else u.push_back(i<<6);
hash[u]=0;
Q.push(u);
while(!Q.empty()){
u=Q.front();
Q.pop();
int x=hash[u],cnt;
for(int ch=‘0‘;ch<=‘1‘;++ch){
cnt=0;
v.clear();
for(int i=0;i<(int)u.size();++i){
int which=u[i]>>6,where=u[i]&63;
if(s[which][where]^ch) continue;
if(++where==s[which].size()) {
++cnt;
for(int j=1;j<=n;++j) v.push_back(j<<6);
}
else v.push_back(which<<6|where);
}
if(cnt>=3) {printf("%d\n",x+1);exit(0);}
sort(v.begin(),v.end());
t.clear();
for(int i=0;i<v.size();++i)
if(i<2||v[i]^v[i-2]) t.push_back(v[i]); //必須是i<m(m>=2)的形式,因為題幹要求3個即可退出
int &th=hash[t];
if(t.size()&&!th) th=x+1,Q.push(t);
}
}
puts("-1");
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i) cin>>s[i];
work();
return 0;
}
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<queue> #include<string> #include<map> using namespace std; typedef vector<int> ve; map<ve,int>hash; queue<ve>Q; string s[35]; int
n; void work(){ ve u,v; for(int i=1;i<=n;++i) if(s[i]=="") {puts("0");exit(0);} else u.push_back(i<<6); hash[u]=0; Q.push(u); while(!Q.empty()){ u=Q.front(); Q.pop(); int x=hash[u],cnt; for(int ch=‘0‘;ch<=‘1‘;++ch){ cnt=0; v.clear(); for(int i=0;i<(int)u.size();++i){ int which=u[i]>>6,where=u[i]&63; if(s[which][where]^ch) continue; if(++where==s[which].size()) { ++cnt; for(int j=1;j<=n;++j) v.push_back(j<<6); } else v.push_back(which<<6|where); } if(cnt>=3) {printf("%d\n",x+1);exit(0);} sort(v.begin(),v.end()); //也可以直接將v壓入隊列,但是要先排序 int &th=hash[v]; if(v.size()&&!th) th=x+1,Q.push(v); } } puts("-1"); } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) cin>>s[i]; work(); return 0; }

BZOJ1080 暴力+位移運算符的用法