54分求助 有详细注释
查看原帖
54分求助 有详细注释
106619
yagyagyag楼主2020/7/3 15:04
#include<bits/stdc++.h>
using namespace std;
int r,c;
int tot=0;
char ch[55][55];
bool used[55][55];
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int g[55][55],begin[2505][2];
int visit[55][55];
void dfs(int x,int y)
{
    visit[x][y]=tot;//同一块大陆标为相同记号 
    for (int i=0;i<=3;i++){
        int xx=x+dx[i],yy=y+dy[i];
        if (xx>=1 && xx<=r && yy>=1 && yy<=c && visit[xx][yy]==0 && ch[xx][yy]=='X')
            dfs(xx,yy);
    }
}
struct mm{
    int x,y,step;
    mm(int a,int b,int c){
        x=a;y=b;step=c;
    }
};
void bfs(int x)
{
    queue<mm> q;
    q.push(mm(begin[x][0],begin[x][1],0));//把该连通块的某个点作为起点  
    while (!q.empty()){
        mm head=q.front(); q.pop();
        if (visit[head.x][head.y]!=x && ch[head.x][head.y]=='X' && g[x][visit[head.x][head.y]]==0)//属于不同连通块且该连通块没有被计算过 
            g[visit[head.x][head.y]][x]=g[x][visit[head.x][head.y]]=head.step;//就记录两连通块的最短距离 
        for (int i=0;i<=3;i++){
            int xx=head.x+dx[i],yy=head.y+dy[i];//走啊走,游啊游  
            if (xx>=1 && xx<=r && yy>=1 && yy<=c && used[xx][yy]==0 && ch[xx][yy]!='.'){
                used[xx][yy]=1;
                int cost=0;
                if (ch[head.x][head.y]=='X'){//X到X经过0个浅水,X到S经过一个浅水  
                    if (ch[xx][yy]=='X') cost=0;
                    if (ch[xx][yy]=='S') cost=1;
                }
                if (ch[head.x][head.y]=='S'){//S到S经过1个浅水,S到X经过0个浅水
                    if (ch[xx][yy]=='S') cost=1;
                    if (ch[xx][yy]=='X') cost=0;
                }
                q.push(mm(xx,yy,head.step+cost));//累加浅水的数目 
            }
        }
    }
}
int dp[1<<16][25];
int main()
{
    //我对本题的思路   求出两两连通块(大陆)间的距离,然后用哈密顿距离模板来计算 
    cin>>r>>c;
    for (int i=1;i<=r;i++){
        for (int j=1;j<=c;j++){
            cin>>ch[i][j];
        }
    }
    for (int i=1;i<=r;i++)
        for (int j=1;j<=c;j++){
            if (visit[i][j]==0 && ch[i][j]=='X'){//dfs把联通块标记为tot 
                tot++;
                dfs(i,j);
                begin[tot][0]=i;begin[tot][1]=j;//记录下该联通块中的某个点 
            }
        }
    for (int i=1;i<=tot;i++){//每个联通块的某个点都拿去计算一下 
        memset(used,0,sizeof used);
        bfs(i);//bfs求联通块两两间的距离 
    }
    memset(dp,0x3f,sizeof dp);//求哈密顿距离模板 
    dp[1][1]=0;
    for (int i=0;i<(1<<tot);i++){
        for (int now=1;now<=tot;now++){
            if (!(i>>(now-1)&1)){
                for (int pre=1;pre<=tot;pre++){
                    if (i>>(pre-1)&1){
                        dp[i|(1<<(now-1))][now]=min(dp[i|(1<<(now-1))][now],dp[i|(1<<(pre-1))][pre]+g[pre][now]);
                    }
                }
            }
        }
    }
    cout<<dp[(1<<tot)-1][tot];
    return 0;
 } 
2020/7/3 15:04
加载中...