zoukankan      html  css  js  c++  java
  • bzoj3571: [Hnoi2014]画框 最小乘积匹配+最小乘积XX总结,

    思路大概同bzoj2395(传送门:http://www.cnblogs.com/DUXT/p/5739864.html),还是将每一种匹配方案的Σai看成x,Σbi看成y,然后将每种方案转化为平面上的点,再用km去找最远的点就行了。

    然而几个月前就学过km且到现在还未写过一道km的题的我并不知道km如何对于负权给出最优解。。。。

    #define XX 某传统算法(例如:最小生成树,二分图最优带权匹配什么的)

    顺便总结一下最小乘积XX

    即对于XX引入两个权值的概念(或是多个权值,一般是两个),看似无从下手,却可以将每一组可行解的方案的两个sum转化为平面内一个点,然后就可以发现一个十分优美的性质即最优解一定在凸包上,于是可以利用一种类似于快包算法的算法,依旧是用XX找出一定在凸包上的两个点,然后再次利用XX进行分治,递归地下去找,弄清楚边界条件(一般一个叉乘就可以轻松搞定),这样问题就被轻易地解决了。(貌似知道了这样的一个模板,基本所有类似问题都可以得到解决)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 #define maxn 100
     8 #define inf 100000000
     9  
    10 int cases,n;
    11 int a[maxn][maxn],b[maxn][maxn],val[maxn][maxn],slack[maxn],valx[maxn],valy[maxn],linky[maxn];
    12 bool visx[maxn],visy[maxn];
    13  
    14 struct point{
    15     int x,y;
    16 }ans;
    17  
    18 point operator -(point a,point b){return(point){a.x-b.x,a.y-b.y};}
    19 double operator *(point a,point b){return a.x*b.y-a.y*b.x;}
    20  
    21 bool find(int x){
    22     visx[x]=1;
    23     for (int y=1;y<=n;y++)
    24         if (!visy[y]){
    25             int t=valx[x]+valy[y]-val[x][y];
    26             if (!t){
    27                 visy[y]=1;
    28                 if (!linky[y]||find(linky[y])){
    29                     linky[y]=x;
    30                     return 1;
    31                 }
    32             }
    33             else slack[y]=min(slack[y],t);
    34         }
    35     return 0;
    36 }
    37  
    38 point km(){
    39     memset(valx,0,sizeof(valx));
    40     memset(valy,0,sizeof(valy));
    41     memset(linky,0,sizeof(linky));
    42     for (int i=1;i<=n;i++)
    43         for (int j=1;j<=n;j++)
    44             valx[i]=max(valx[i],val[i][j]);
    45     for (int x=1;x<=n;x++){
    46         memset(slack,63,sizeof(slack));
    47         while (1){
    48             memset(visx,0,sizeof(visx));
    49             memset(visy,0,sizeof(visy));
    50             if (find(x)) break;
    51             int d=inf;
    52             for (int i=1;i<=n;i++) if (!visy[i]) d=min(d,slack[i]);
    53             for (int i=1;i<=n;i++) if (visx[i]) valx[i]-=d;
    54             for (int i=1;i<=n;i++) if (visy[i]) valy[i]+=d;
    55         }
    56     }
    57     point now={0,0};
    58     for (int i=1;i<=n;i++) now.x+=a[linky[i]][i],now.y+=b[linky[i]][i];
    59     if ((ans.x==inf&&ans.y==inf)||(ans.x*ans.y>now.x*now.y)) ans=now;
    60     return now;
    61 }
    62  
    63 bool operator ==(point a,point b){return a.x==b.x&&a.y==b.y;} 
    64  
    65 void solve(point x,point y){
    66     for (int i=1;i<=n;i++)
    67         for (int j=1;j<=n;j++)
    68             val[i][j]=b[i][j]*(x.x-y.x)+a[i][j]*(y.y-x.y);
    69     point z=km();
    70     if ((z-x)*(y-z)<=0) return;
    71     solve(x,z);
    72     solve(z,y);
    73 }
    74  
    75 int main(){
    76     scanf("%d",&cases);
    77     while (cases--){
    78         scanf("%d",&n);
    79         ans.x=ans.y=inf;
    80         for (int i=1;i<=n;i++)
    81             for (int j=1;j<=n;j++) scanf("%d",&a[i][j]);
    82         for (int i=1;i<=n;i++)
    83             for (int j=1;j<=n;j++) scanf("%d",&b[i][j]);
    84         point minx,miny;
    85         for (int i=1;i<=n;i++) 
    86             for (int j=1;j<=n;j++) val[i][j]=-a[i][j];
    87         minx=km();
    88         for (int i=1;i<=n;i++)
    89             for (int j=1;j<=n;j++) val[i][j]=-b[i][j];
    90         miny=km();
    91         solve(minx,miny);
    92         printf("%d
    ",ans.x*ans.y);
    93     }
    94     return 0;
    95 }
    View Code
  • 相关阅读:
    OpenOffice 在 Linux 下安装使用
    LINUX环境使用rpm命令安装gcc
    用shell脚本执行mysql脚本
    CentOS 7下用firewall-cmd控制端口与端口转发详解(转载)
    Hive字段中文注释乱码解决办法
    真正从零开始,TensorFlow详细安装入门图文教程!
    九、Oracle SQL(优化专题&分表分区)
    八、Oracle SQL(聚合函数&标量函数)
    七、Oracle SQL(Oracle 定时任务基础)
    六、Oracle SQL(游标&RECORD&存过、游标、RECORD整合)
  • 原文地址:https://www.cnblogs.com/DUXT/p/5742995.html
Copyright © 2011-2022 走看看