[HAOI2008] 移动玩具

观察到给定的两个方框都是4*4的,能想到记忆化搜索,当然,将记忆化搜索换个顺序就是dp

将每一位是否有玩具用0/1表示,最后生成一个16位的0/1序列,将起点终点的0/1序列处理出来,用类似bfs的方式存下可能对答案有贡献的状态,每一次枚举每一个有玩具的位置,枚举能到达的位置,进行转移。

using namespace std;
#define ll long long
#define MAXN 1<<17
inline ll read(){
	ll x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
ll mp1[5][5],mp2[5][5],dp[MAXN];
ll st,ed;
ll ad_x[4]={0,1,0,-1},ad_y[4]={1,0,-1,0};
ll id(ll x,ll y){
	return 1<<((x-1)*4+y-1);
}
int main(){
	string s;
	for(int i=1;i<=4;i++){
		cin>>s;
		for(int j=1;j<=4;j++){
			mp1[i][j]=s[j-1]-'0';
		}
	}
	for(int i=1;i<=4;i++){
		cin>>s;
		for(int j=1;j<=4;j++){
			mp2[i][j]=s[j-1]-'0';
			if(mp2[i][j]&mp1[i][j]){
				mp2[i][j]=mp1[i][j]=0;
			}
		}
	}
	for(int i=1;i<=4;i++){
		for(int j=1;j<=4;j++){
			if(mp1[i][j])st|=id(i,j);
		}
	}
	for(int i=1;i<=4;i++){
		for(int j=1;j<=4;j++){
			if(mp2[i][j])ed|=id(i,j);
		}
	}
	queue<ll> q;
	memset(dp,0x3f,sizeof(dp));
	dp[st]=0;
	q.push(st);
	while(!q.empty()){
		ll now=q.front();
		q.pop();
		if(now==ed)break;
//		cout<<now<<endl;
		for(int x=1;x<=4;x++){
			for(int y=1;y<=4;y++){
				if(!(now&id(x,y)))continue;
				for(int u=0;u<4;u++){
					ll _x=x+ad_x[u],_y=y+ad_y[u];
					if(_x<1||_x>4||_y<1||_y>4||now&id(_x,_y))continue;
					ll p=now^id(_x,_y)^id(x,y);
//					cout<<p<<" ";
					if(dp[now]+1<dp[p]){
						dp[p]=dp[now]+1;
						q.push(p);
					}
				}
			}
		}
//		cout<<"\n------------\n";
	}
	cout<<dp[ed];
	return 0;
}
posted @ 2024-11-24 19:49  flyfreemrn  阅读(8)  评论(0)    收藏  举报