CF1874B
感觉挺有意思的题,写了 2h 多然后没脑子写 C 光荣掉分。
首先这题操作全是位运算所以位之间独立,从而,对于两个不同的位而言,如果他们的初始状态相同,经过的操作也相同,那么结果相同。
也就是说,虽然输入的
如果两位对应的
否则,我们可以把
也就是对于一位的每一种初始状态
预处理:跑一遍初始状态为
对于每一组输入,对于以上每种初始状态,我们都可以处理出一个限制
注意预处理一下没有限制的情况。可以把这个也当成一种目标状态,总状态数就是
时间复杂度:
#include<bits/stdc++.h>
using namespace std;
int dis[100005];
int from[100005],op[100005];
int f1(int x){
//f1和f2反了
x|=(x&(1<<1))>>1;
x|=(x&(1<<3))>>1;
x|=(x&(1<<5))>>1;
x|=(x&(1<<7))>>1;
x|=(x&(1<<9))>>1;
x|=(x&(1<<11))>>1;
x|=(x&(1<<13))>>1;
x|=(x&(1<<15))>>1;
return x;
}
int f2(int x){
x&=((1<<16)-1)^((x&(1<<1))>>1)^(1<<0);
x&=((1<<16)-1)^((x&(1<<3))>>1)^(1<<2);
x&=((1<<16)-1)^((x&(1<<5))>>1)^(1<<4);
x&=((1<<16)-1)^((x&(1<<7))>>1)^(1<<6);
x&=((1<<16)-1)^((x&(1<<9))>>1)^(1<<8);
x&=((1<<16)-1)^((x&(1<<11))>>1)^(1<<10);
x&=((1<<16)-1)^((x&(1<<13))>>1)^(1<<12);
x&=((1<<16)-1)^((x&(1<<15))>>1)^(1<<14);
return x;
}
int f3(int x){
x^=(x&(1<<0))<<1;
x^=(x&(1<<2))<<1;
x^=(x&(1<<4))<<1;
x^=(x&(1<<6))<<1;
x^=(x&(1<<8))<<1;
x^=(x&(1<<10))<<1;
x^=(x&(1<<12))<<1;
x^=(x&(1<<14))<<1;
return x;
}
int f4(int x){
x^=(1<<9);
x^=(1<<11);
x^=(1<<13);
x^=(1<<15);
return x;
}
queue<int>q;
int tmp[15];
int ans[1000005];
int p5[10];
void output(int x){
for(int i=0;i<16;i++)printf("%d",(x>>i)&1);printf("\n");
}
int main(){
int T;
p5[0]=1;
for(int i=1;i<=8;i++)p5[i]=p5[i-1]*5;
scanf("%d",&T);
memset(dis,0x3f,sizeof(dis));
int S=0b1110010011100100;//初始状态
dis[S]=0;
q.push(S);
//bfs
while(!q.empty()){
int f=q.front();
q.pop();
int p1=f1(f),p2=f2(f),p3=f3(f),p4=f4(f);
if(dis[p1]>dis[f]+1){
dis[p1]=dis[f]+1;
q.push(p1);
from[p1]=f;
op[p1]=1;
}
if(dis[p2]>dis[f]+1){
dis[p2]=dis[f]+1;
q.push(p2);
from[p2]=f;
op[p2]=2;
}
if(dis[p3]>dis[f]+1){
dis[p3]=dis[f]+1;
q.push(p3);
from[p3]=f;
op[p3]=3;
}
if(dis[p4]>dis[f]+1){
dis[p4]=dis[f]+1;
q.push(p4);
from[p4]=f;
op[p4]=4;
}
}
memset(ans,0x3f,sizeof(ans));
for(int i=0;i<(1<<16);i++){
for(int j=0;j<8;j++)tmp[j]=i/((1<<j)<<j)%4;
int x=0;
for(int j=0;j<8;j++)x+=tmp[j]*p5[j];
ans[x]=dis[i];
}
//处理没有限制的情况
for(int i=0;i<p5[8];i++){
int pos=-1;
for(int j=0;j<8;j++)if(i/p5[j]%5==4)pos=j;
if(pos==-1)continue;
for(int j=1;j<=4;j++)ans[i]=min(ans[i],ans[i-p5[pos]*j]);
}
while(T--){
int a,b,c,d,m;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&m);
for(int i=0;i<8;i++)tmp[i]=4;
int fl=0;
for(int i=0;i<30;i++){
//对应初始状态和目标状态
int da=((a>>i)&1);
int db=((b>>i)&1);
int dc=((c>>i)&1);
int dd=((d>>i)&1);
int dm=((m>>i)&1);
int id=(dm<<2)+(db<<1)+da;
int val=(dd<<1)+dc;
if(tmp[id]!=4 && tmp[id]!=val)fl=1;
tmp[id]=val;
}
if(fl==1){
printf("-1\n");
continue;
}
int x=0;
for(int j=0;j<8;j++)x+=tmp[j]*p5[j];
if(ans[x]==0x3f3f3f3f)printf("-1\n");
else printf("%d\n",ans[x]);
}
return 0;
}