前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Luogu P4772 灰化肥,会挥发 题解

Luogu P4772 灰化肥,会挥发 题解

作者头像
yzxoi
发布2022-09-19 11:36:51
2640
发布2022-09-19 11:36:51
举报
文章被收录于专栏:OI

Luogu P4772 灰化肥,会挥发 题解

Description

在Farmer Justin的农场中有许多灰化肥,它们都堆积在A仓库里。为了方便施肥,Farmer Justin需要修一些公路使得他能用拖拉机把这些灰化肥拉到其他仓库里。由于Farmer Justin及其懒惰,所以他只想一次拉完所有的灰化肥送到其他仓库里。但是灰化肥见光易挥发,所以Farmer Justin需要尽快把这些灰化肥拉完。现在告诉你Farmer Justin农场的构成地图,请你帮帮他计划一条从A仓库出发走完所有仓库的方案吧!由于Farmer Justin非常的讨厌浪费时间,所以你只需要告诉他最短的距离和走过所有农场的顺序。(注意:拖拉机走的时候是四联通的。)

Solution

状压DP+BFS

首先先暴力BFS跑出任意两个点之间的距离。

然后考虑DP,设dp[i][j]表示当前已经遍历过的点状态为i,最后一个遍历的点为j的最小值。

很明显:

dp[i][j]=dp[i\oplus (1<<k-1)][k]+cost[k][j](i\&(1<<k-1)!=0)

又因为要记录路径,于是开一个数组gdp类似,更新的过程中记录下路径即可。

注意要开long long。

Code

代码语言:javascript
复制
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int dx[]={0,0,1,-1},
          dy[]={1,-1,0,0};
int r,c,n,cost[20][20],dis[510][510],Min,f[1<<16][16];
char a[510][510];
string Ans,g[1<<16][16];
struct node{int x,y;}G[20];
queue<node> q;
inline void bfs(int x){
memset(dis,0,sizeof(dis));
while(!q.empty()) q.pop();
q.push(G[x]);dis[G[x].x][G[x].y]=1;
while(!q.empty()){
node u=q.front();q.pop();
for(int i=0;i<4;i++){
int xx=u.x+dx[i],yy=u.y+dy[i];
if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&a[xx][yy]!='*'&&!dis[xx][yy]){
dis[xx][yy]=dis[u.x][u.y]+1;
q.push((node){xx,yy});
}
}
}
}
signed main(){
scanf("%lld%lld%lld",&r,&c,&n);
for(int i=1;i<=r;i++) cin>>a[i]+1;
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
if('A'<=a[i][j]&&a[i][j]<='Z') G[a[i][j]-'A'+1]=(node){i,j};
for(int i=1;i<=n;i++){
bfs(i);
for(int j=1;j<=n;j++) cost[i][j]=dis[G[j].x][G[j].y]-1;
}
memset(f,63,sizeof(f));
f[1][1]=0;
g[1][1]='A';
for(int i=2;i<(1<<n);i++){
if(!(i&1)) continue ;
for(int j=1;j<=n;j++){
if(!(i&(1<<j-1))) continue ;
for(int k=2;k<=n;k++){
if(!(i&(1<<k-1))j==k) continue ;
if(f[i][k]>f[i^(1<<k-1)][j]+cost[j][k]) f[i][k]=f[i^(1<<k-1)][j]+cost[j][k],g[i][k]=g[i^(1<<k-1)][j]+char(k+'A'-1);
else if(f[i][k]==f[i^(1<<k-1)][j]+cost[j][k]&&g[i][k]>g[i^(1<<k-1)][j]+char(k+'A'-1)) g[i][k]=g[i^(1<<k-1)][j]+char(k+'A'-1);
}
}
}
Min=f[(1<<n)-1][2];Ans=g[(1<<n)-1][2];
for(int i=3;i<=n;i++)
if(Min>f[(1<<n)-1][i]) Min=f[(1<<n)-1][i],Ans=g[(1<<n)-1][i];
else if(Min==f[(1<<n)-1][i]&&Ans>g[(1<<n)-1][i]) Ans=g[(1<<n)-1][i];
    return printf("%lld\n",Min),cout<<Ans<<endl,0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-09-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Luogu P4772 灰化肥,会挥发 题解
    • Description
      • Solution
        • Code
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档