zoukankan      html  css  js  c++  java
  • bzoj2539

    题解:

    KM匹配

    注意判断不能在一条直线上

    然后大小写相同

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4005;
    map<string,int> MP;
    float R,x[N],y[N];
    int G[N][N],n,p,a,b,l[N],r[N],slack[N],con[N],vy[N],vx[N];
    int on(int a,int b,int c)
    {
        if (x[a]==x[b]&&x[b]==x[c])
         return (min(y[a],y[b])<=y[c]&&y[c]<=max(y[a],y[b]));
        return ((y[a]-y[b])*(x[c]-x[b])==(y[c]-y[b])*(x[a]-x[b]));
    }
    int Judge(int a,int b)
    {
        if (x[a]>x[b]) swap(a,b);
        for (int i=1;i<=n*2;i++)
         if (i!=a&&i!=b&&x[a]<=x[i]&&x[i]<=x[b])
        if (on(a,b,i)) return 0;
        return 1;
    }
    float dis(int a,int b)
    {
        return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);
    }
    void Preoperate()
    {
        memset(l,0,sizeof(l));
        for (int i=1;i<=2*n;i++)
         for (int j=1;j<=2*n;j++) l[i]=max(l[i],G[i][j]);
        memset(r,0,sizeof(r));
    }
    int find(int x)
    {
        vx[x]=1;
        for (int i=n+1;i<=2*n;i++)
         if (!vy[i])
          {
            if (G[x][i]==l[x]+r[i])
             {
                vy[i]=1;
                if (con[i]==-1||find(con[i]))
                 {
                    con[i]=x;
                    return 1;
                 }
             }
            else slack[i]=min(slack[i],l[x]+r[i]-G[x][i]);
         }
        return 0;
    }
    int main()
    {
        memset(G,-0x3f,sizeof(G));
        string str;
        scanf("%f%d",&R,&n);
        for (int i=1;i<=2*n;i++)
         {
            scanf("%f %f",&x[i],&y[i]);
            cin>>str;
            for (int j=0;j<str.length();j++)
             if (str[j]<='Z'&&str[j]>='A') str[j]+='a'-'A';
            MP[str]=i;
        }
        while (1)
         {
            cin>>str;
            if (str=="End") break;
            for (int i=0;i<str.length();i++)
             if (str[i]<='Z'&&str[i]>='A') str[i]+='a'-'A';
            a=MP[str];
            cin>>str;
            for (int i=0;i<str.length();i++) 
             if (str[i]<='Z'&&str[i]>='A') str[i]+='a'-'A';
            b=MP[str];
            scanf("%d",&p);
            if (a>b) swap(a,b);
            if (dis(a,b)<=R*R&&Judge(a,b)) G[a][b]=p;
         }
        for (int i=1;i<=n;i++)
         for (int j=n+1;j<=2*n;j++)
          if(G[i][j]<0&&dis(i,j)<=R*R&&Judge(i,j)) G[i][j]=1;
        Preoperate();
        memset(con,-1,sizeof(con));
        for (int j=1;j<=n;j++)
         {
            for (int k=1;k<=1000;k++)
             {
                memset(slack,127,sizeof(slack));
                memset(vx,0,sizeof(vx));
                memset(vy,0,sizeof(vy));
                if (find(j)) break;
                int d=2e9;
                for (int i=n+1;i<=n*2;i++)
                 if (!vy[i]) d=min(d,slack[i]);
                for (int i=1;i<=n;i++)
                 if(vx[i]) l[i]-=d;
                for (int i=n+1;i<=n*2;i++)
                 if(vy[i]) r[i]+=d;
             }
         }
        int ans=0;
        for (int i=1;i<=n*2;i++)
         if (con[i]!=-1) ans+=G[con[i]][i];
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    设计模式-代理模式
    设计模式-桥接模式
    设计模式-组合模式
    设计模式-享元模式
    设计模式-适配器模式
    设计模式-装饰器模式
    设计模式-外观模式
    redis日志格式
    Linux下的文件切割和文件合并
    Windows server 服务器的端口突然远程连不上了,但是可以远程连接,怎么回事?
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8297875.html
Copyright © 2011-2022 走看看