bfs+状态压缩dp

题目连接

题解 : 对两两管道进行bfs,然后用dp[i][j] 来表示在i状态下通过了前j个管道

参考博客

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define de(x) cout << #x << "=" << x << endl
#define rep(i,a,b) for(int i=a;i<(b);++i)
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()
#define pb push_back
#define fi first
#define se second
const int inf = 0x3f3f3f3f;
const int N = 1e5+5;
char mp[20][20];
struct Pipe{
	int x1,x2,y1,y2;
}a[20];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int dis[20][20];
int pp[20][20];
int dp[1<<15][20];
int n,m;
int bfs(Pipe a,Pipe b)
{
	queue<pii>que;
	int nx,ny;
	memset(dis,-1,sizeof(dis));
	dis[a.x2][a.y2]=0;
	que.push(pii(a.x2,a.y2));
	while(!que.empty())
	{
		pii u=que.front();
		que.pop();
		if(u.fi==b.x1&&u.se==b.y1) return dis[u.fi][u.se];
		for(int i=0;i<4;i++)
		{
			nx=u.fi+dx[i],ny=u.se+dy[i];
			if(nx>n||nx<=0||ny>n||ny<=0||mp[nx][ny]=='#'||dis[nx][ny]!=-1) continue;
			dis[nx][ny]=dis[u.fi][u.se]+1;
			que.push(pii(nx,ny));
		}
	}
	return -1;
}
void init()
{
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(i==j) pp[i][j]=0;
			else pp[i][j]=bfs(a[i],a[j]);
		}
	}
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=1;i<=n;i++)
			scanf("%s",mp[i]+1);
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
		}
		init();
		memset(dp,inf,sizeof(dp));
		for(int i=1;i<=m;i++)
		{
			dp[1<<(i-1)][i]=0;
		}
		int ans=inf;
		for(int i=0;i<(1<<m);i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(i&(1<<(j-1)))//i状态下有第j个管道才能进行
				{
					for(int k=1;k<=m;k++)
					{
						if(i&(1<<(k-1))==0||pp[k][j]==-1) continue;//同理
						dp[i][j]=min(dp[i^(1<<(j-1))][k]+pp[k][j],dp[i][j]);
					}	
				}
				if(i==(1<<m)-1) ans=min(ans,dp[i][j]);
			}
		}
		if(ans==inf) cout<<"-1
";
		else cout<<ans<<endl;
	}
}
原文地址:https://www.cnblogs.com/q1076452761/p/7689195.html