zoukankan      html  css  js  c++  java
  • poj 3565 Ants

    Problem Description

    一个棋盘,有n个黑点和n个白点,求一种方案让黑白点两两配对且任意一对黑白点之间的连线不相交

    思路:因为所有线段不相交,所以每条线段长度之和最小,因为必然有一种方案,所以是完全匹配,把点点间距离取反,跑一个KM最大带权匹配就好了

    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int N = 220;
    const double eps = 1e-6;
    const int INF = 1e9;
    double g[N][N], la[N], lb[N], delta;
    bool va[N], vb[N];
    int n,mat[N],ans[N];
    double dist(int x1,int y1,int x2,int y2){
        int tx = x1 - x2, ty = y1 - y2;
        return -sqrt(tx * tx + ty * ty);
    }
    bool che(double x){  return fabs(x) < eps;}
    bool dfs(int x){
        va[x] = 1;
        for(int y = 1; y <= n; y++){
            if(!vb[y])
              if(che(la[x] + lb[y] - g[x][y])){
                vb[y] = 1;
                if(!mat[y] || dfs(mat[y])){
                    mat[y] = x;
                    return 1;
                }
              }
        }
        return 0;
    }
    void update() {  
        delta = 1e10;  
        for (int i = 1; i <= n; i ++) if (va[i]) {  
            for (int j = 1; j <= n; j ++) if (!vb[j]) {  
                delta = min(delta, la[i] + lb[j] - g[i][j]);  
            }  
        }  
        for (int i = 1; i <= n; i ++) {  
            la[i] -= va[i] ? delta : 0;  
            lb[i] += vb[i] ? delta : 0;  
        }  
    }  
    void KM(){
        for(int i = 1; i <= n; i++){
            la[i] = -INF; lb[i] = 0;
            for(int j = 1; j <= n; j++)
              la[i] = max(la[i],g[i][j]);
        }
        for(int i = 1; i <= n; i++)
          while(1){
            memset(va,0,sizeof(va));
            memset(vb,0,sizeof(vb));
            if(dfs(i)) break;
            update();
          }
        return ;
    }
    void init(){
        memset(g,0,sizeof(g));
        memset(la,0,sizeof(la));
        memset(lb,0,sizeof(lb));
        memset(ans,0,sizeof(ans));
    }
    int main(){
        ios::sync_with_stdio(false);
        double x[110], y[110];
        while(cin>>n){
            init();
            for(int i = 1; i <= n; i++)
              cin>>x[i]>>y[i];
                double xx,yy;
            for(int i = 1; i <= n; i++){
                cin>>xx>>yy;
                for(int j = 1; j <= n; j++)
                  g[j][i] = dist(x[j],y[j],xx,yy);
            }
            KM();
            for(int i = 1; i <= n; i++)
              ans[mat[i]] = i;
            for(int i = 1; i <= n; i++)
              cout<<ans[i]<<endl;
        }
        return 0;
    }
  • 相关阅读:
    微信小程序 editor富文本
    vuex详解
    每日一练
    如何有效地进行代码 Review?
    vue实现瀑布流
    浅谈js防抖和节流-转载
    Java Kafka 消费积压监控
    用于文本内容的复制粘贴
    Java 键值对数据本地保存与读取
    Java ElasticSearch 操作
  • 原文地址:https://www.cnblogs.com/Rorshach/p/8682989.html
Copyright © 2011-2022 走看看