P1585

魔法阵

题目描述

魔法阵是一个n×m的格子(高n,宽m),n×m为偶数。Smart手中有n×m个宝石(以1~n×m编号)。Smart从最右上角的格子开始走,从一个格子可以走到上、下、左、右4个相邻的格子,但不能走出边界。每个格子必须且仅能到过1次,这样Smart一共走了n×m个格子停止(随便停哪里)。Smart每进入一个格子,就在该格子里放入一颗宝石。他是按顺序放的,也就是说——第i个进入的格子放入i号宝石。

   如果两颗宝石的编号对n×m÷2取模的值相同,则认为这两颗宝石相互之间有微妙的影响。也就是说,我们按照宝石的编号对n×m÷2取模的值,将宝石分成n×m÷2对,其中每对都恰有两颗宝石。对于每一对宝石,设第一颗宝石在第a行第b列,另一颗宝石在第c行第d列,那么定义这2个宝石的魔力影响值为 k1×|a-c|+k2×|b-d|。
需要你求出的是,在所有合乎题意的宝石摆放方案中,所有成对的宝石间的最大魔力影响值的最小值为多少。换句话说,如果我们定义对n×m÷2取模的值为i的一对宝石的魔力影响值为a[i]。你需要求出的就是max{a[i]|i=0,1,2...}的最小值。

输入格式

只有一行用空格隔开的4个整数,分别是n、m、k1、k2。(n×m≤50,0<k1,k2≤32767)

输出格式

只需输出一个整数,即题目所要求的“所有成对的宝石间的最大魔力影响值的最小值”。

样例 #1

样例输入 #1

2 2 2 2

样例输出 #1

4
关于一笔画搜索问题有一个很有效的可行性剪枝
我们如果发现当前点的上下走过了 但是左右未走过
或者左右走过来 但是上下未走过 那么不可能走完整个方阵 直接return
这种做法要注意先预处理边界
`for(int i=0;i<=n+1;i++)
	vis[i][0]=vis[i][m+1]=1;
for(int i=0;i<=m+1;i++)
	vis[0][i]=vis[n+1][i]=1;
`
不然还是要TLE
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,k1,k2;
int vis[55][55];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int jl[30][3][2];
int minn=INT_MAX;
int mod,tim;
void dfs(int x,int y,int cnt,int maxx)
{
	if(cnt==n*m)
	{
		int v=cnt%mod;
		int cost=k1*abs(jl[v][1][0]-x)+k2*abs(jl[v][1][1]-y);
		minn=min(minn,max(maxx,cost));
	}
	if(maxx>=minn)return ;
	if(vis[x-1][y]&&vis[x+1][y]&&!vis[x][y-1]&&!vis[x][y+1])return ;
	if(!vis[x-1][y]&&!vis[x+1][y]&&vis[x][y-1]&&vis[x][y+1])return ;
	for(int i=0;i<4;i++)
	{
		int nx=x+dx[i],ny=y+dy[i];
		if(nx<1||nx>n||ny<1||ny>m||vis[nx][ny])continue;
		int v=cnt%mod;
		if(jl[v][1][0])
		{
			jl[v][2][0]=x,jl[v][2][1]=y;
			vis[nx][ny]=1;
			int cost=k1*abs(jl[v][1][0]-x)+k2*abs(jl[v][1][1]-y);
			maxx=max(maxx,cost);
			dfs(nx,ny,cnt+1,maxx);
			jl[v][2][0]=0,jl[v][2][1]=0;
			vis[nx][ny]=0;
		}
		else
		{
			jl[v][1][0]=x,jl[v][1][1]=y;
			vis[nx][ny]=1;
			dfs(nx,ny,cnt+1,maxx);
			jl[v][1][0]=0,jl[v][1][1]=0;
			vis[nx][ny]=0;
		}
	}
}
signed main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m>>k1>>k2;
	mod=n*m/2;
	for(int i=0;i<=n+1;i++)
		vis[i][0]=vis[i][m+1]=1;
	for(int i=0;i<=m+1;i++)
		vis[0][i]=vis[n+1][i]=1;
	jl[1][1][0]=1,jl[1][1][1]=1;vis[1][1]=1;
	dfs(1,1,1,-INT_MAX);
	cout<<minn<<"\n";
	return 0;
}
posted @ 2023-01-29 14:13  PKU_IMCOMING  阅读(34)  评论(0)    收藏  举报