BZOJ1080 暴力+位移运算符的用法
Posted Billyshuai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1080 暴力+位移运算符的用法相关的知识,希望对你有一定的参考价值。
1080: [SCOI2008]劣质编码
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 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
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<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 暴力+位移运算符的用法的主要内容,如果未能解决你的问题,请参考以下文章