zoukankan      html  css  js  c++  java
  • UVA1045 The Great Wall Game(二分图最佳匹配)

    题意:在一个n*n的棋盘上有n个棋子,要求通过移动棋子使棋子的排布满足以下情况之一:呈横行排列;呈纵行排列;呈对角线排列(有两条)。

    棋子移动一个单元格的费用为1,总费用为所有棋子的移动费用之和。求最小费用。

    分析:因为这题的数据很小,故可以枚举每种情况.对于每种情况,我们可以用二分匹配的方法算出最小费用(对于每个棋子,连接n条边到n个目标位置,权值设为负,这样最佳二分匹配求的最大值就是答案的最小值了);

    // File Name: 1045.cpp
    // Author: Zlbing
    // Created Time: 2013/4/20 15:58:22
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 1000000000
    #define LL long long
    #define REP(i,r,n) for(int i=r;i<=n;i++)
    #define RREP(i,n,r) for(int i=n;i>=r;i--)
    const int MAXN=20;
    int X[MAXN],Y[MAXN];
    int Left[MAXN];
    int w[MAXN][MAXN];
    int Lx[MAXN],Ly[MAXN];
    bool S[MAXN],T[MAXN];
    int N;
    bool match(int i)
    {
        S[i]=true;
        for(int j=1;j<=N;j++)if(Lx[i]+Ly[j]==w[i][j]&&!T[j])
        {
            T[j]=true;
            if(Left[j]==0||match(Left[j]))
            {
                Left[j]=i;
                return true;
            }
        }
        return false;
    }
    void update(){
        int a=INF;
        for(int i=1;i<=N;i++)if(S[i])
            for(int j=1;j<=N;j++)if(!T[j])
                a=min(a,Lx[i]+Ly[j]-w[i][j]);
        for(int i=1;i<=N;i++){
            if(S[i])Lx[i]-=a;
            if(T[i])Ly[i]+=a;
        }
    }
    void KM()
    {
        for(int i=1;i<=N;i++){
            Left[i]=Lx[i]=Ly[i]=0;
            for(int j=1;j<=N;j++)
            {
                Lx[i]=max(Lx[i],w[i][j]);
            }
        }
        for(int i=1;i<=N;i++){
            for(;;){
                CL(S,0);
                CL(T,0);
                if(match(i))break;
                else update();
            }
        }
    }
    
    int main()
    {
        int cas=0;    
        while(~scanf("%d",&N))
        {
            if(N==0)break;
            REP(i,1,N)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                X[i]=a;Y[i]=b;
            }
            int ans=INF;
            REP(i,1,N)
            {
                REP(k,1,N)
                    REP(j,1,N)
                    {
                        int dist=abs(X[k]-i)+abs(Y[k]-j);
                        w[k][j]=-dist;
                    }
                KM();
                int minn=0;
                REP(i,1,N){
                    minn+=-w[Left[i]][i];
                }
                ans=min(ans,minn);
            }
            REP(i,1,N) {
                REP(k,1,N)
                    REP(j,1,N)
                    {
                        int dist=abs(X[k]-j)+abs(Y[k]-i);
                        w[k][j]=-dist;
                    }
                KM();
                int minn=0;
                REP(i,1,N)
                    minn+=-w[Left[i]][i];
                ans=min(ans,minn);
            }
            REP(k,1,N)
                REP(i,1,N)
                {
                    int dist=abs(X[k]-i)+abs(Y[k]-i);
                    w[k][i]=-dist;
                }
            KM();
            int minn=0;
            REP(i,1,N)
                minn+=-w[Left[i]][i];
            ans=min(ans,minn);
            REP(k,1,N)
                REP(i,1,N)
                {
                    int dist=abs(X[k]-i)+abs(Y[k]-N+i-1);
                    w[k][i]=-dist;
                }
            KM();
            minn=0;
            REP(i,1,N)
                minn+=-w[Left[i]][i];
            ans=min(ans,minn);
            printf("Board %d: %d moves required.\n\n",++cas,ans);
        }
        return 0;
    }
  • 相关阅读:
    python的多进程
    sqlalchemy的缓存和刷新
    uuid
    区块链的理解
    列表推导式,两个for循环的例子
    Fiddler 抓包工具总结
    python---webbrowser模块的使用,用非系统默认浏览器打开
    使用jmeter做web接口测试
    selenium2中关于Python的常用函数
    Selenium2+Python自动化学习笔记(第1天)
  • 原文地址:https://www.cnblogs.com/arbitrary/p/3033852.html
Copyright © 2011-2022 走看看