Uva 10888 Warehouse(KM)

来源:互联网 发布:计算机的发展史知乎 编辑:程序博客网 时间:2024/06/06 12:31
题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1829

思路:

1.首先求出每个箱子到达每个目的地的最短距离w。

2.将箱子看做x点,将目的地看做y点,x向y连边,权值为w,求二分图最优匹配即可。

3.是否存在移动过程中路径上有其他箱子阻挡。例如,从A到C的路径上存在B箱子,则此时可以看做将B箱子移动到C后,A移动到B箱子。即最优匹配一定对应着一组可行解。

#include<map>#include<queue>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define F first#define S second#define pii pair<int,int>#define debugusing namespace std;const int N = 20;const int maxn = 45;const int INF = 0x3f3f3f3f;int nx,ny;//两边的点数int g[N][N];//二分图描述int linker[N],lx[N],ly[N];int slack[N];bool visx[N],visy[N];bool DFS(int x){    visx[x] = true;    for(int y = 0; y < ny; y++)    {        if(visy[y])continue;        int tmp = lx[x] + ly[y] - g[x][y];        if(tmp == 0)        {            visy[y] = true;            if(linker[y] == -1 || DFS(linker[y]))            {                linker[y] = x;                return true;            }        }        else if(slack[y] > tmp)            slack[y] = tmp;    }    return false;}int KM(){    memset(linker,-1,sizeof(linker));    memset(ly,0,sizeof(ly));    for(int i = 0; i < nx; i++)    {        lx[i] = -INF;        for(int j = 0; j < ny; j++)            if(g[i][j] > lx[i])                lx[i] = g[i][j];    }    for(int x = 0; x < nx; x++)    {        for(int i = 0; i < ny; i++)            slack[i] = INF;        while(true)        {            memset(visx,false,sizeof(visx));            memset(visy,false,sizeof(visy));            if(DFS(x))break;            int d = INF;            for(int i = 0; i < ny; i++)                if(!visy[i] && d > slack[i])                    d = slack[i];            for(int i = 0; i < nx; i++)                if(visx[i])                    lx[i] -= d;            for(int i = 0; i < ny; i++)            {                if(visy[i])ly[i] += d;                else slack[i] -= d;            }        }    }    int res = 0;    for(int i = 0; i < ny; i++)        if(linker[i] != -1)            res += g[linker[i]][i];    return res;}struct Node{    pii p;    int step;    Node() {}    Node(pii p,int step):p(p),step(step) {}};int n,m;int cntB,cntE;int vis[maxn*maxn];char ch[maxn][maxn];int dx[]= {-1,1,0,0};int dy[]= {0,0,-1,1};queue<Node> q;map<pii,int> box,ed;void init(){    cntB=cntE=0;    box.clear(),ed.clear();}inline int ID(int x,int y){    return x*m+y;}inline int isIn(int x,int y){    return x>=1&&x<=n&&y>=1&&y<=m;}void build(pii p,int id){    memset(vis,0,sizeof(vis));    while(!q.empty()) q.pop();    q.push(Node(p,0));    vis[ID(p.F,p.S)]=1;    while(!q.empty())    {        Node now=q.front();        q.pop();        for(int i=0; i<4; i++)        {            int x=now.p.F+dx[i];            int y=now.p.S+dy[i];            if(isIn(x,y)&&!vis[ID(x,y)]&&ch[x][y]!='#')            {                if(ch[x][y]=='X')                {                    g[id][ed[make_pair(x,y)]]=-(now.step+1);                }                vis[ID(x,y)]=1;                q.push(Node(make_pair(x,y),now.step+1));            }        }    }}void solve(){    for(int i=0;i<box.size();i++)    {        for(int j=0;j<box.size();j++)        {            g[i][j]=-INF;        }    }    int cnt=0;    map<pii,int>::iterator it=box.begin();    for(; it!=box.end(); it++)    {        build(it->F,cnt++);    }    nx=ny=cnt;    printf("%d\n",-KM());}int main(){#ifdef debu    freopen("in.txt","r",stdin);#endif // debug    int t;    scanf("%d",&t);    while(t--)    {        init();        scanf("%d%d",&n,&m);        for(int i=1; i<=n; i++)        {            getchar();            for(int j=1; j<=m; j++)            {                scanf("%c",&ch[i][j]);                if(ch[i][j]=='B') box[make_pair(i,j)]=cntB++;                else if(ch[i][j]=='X') ed[make_pair(i,j)]=cntE++;            }        }        solve();    }    return 0;}



原创粉丝点击