zoukankan      html  css  js  c++  java
  • 【KM】POJ2195/HDU1533-Going home

    //最近没什么时间quq据说长得帅的人都在切八中,然而长得丑的人只能水水裸题

    【题目大意】

    给出一张地图及人和房屋的位置,求出每个人回到不同房屋所具有的最小代价和。

    【思路】

    最小权匹配,先O(n^2)求出每个人到任意房屋的距离后取反,就变成了裸的KM。数据范围很小,O(n^4)可以0ms过。

    【错误点】

    1.slack在每次循环中药重新设置为无穷大。2.内循环和外循环的循环变量重名了。3.变量名取太乱了用错了一次。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 using namespace std;
      7 const int INF=0x7fffffff;
      8 const int MAXN=500;
      9 int n,m;
     10 int mx[MAXN],my[MAXN],hx[MAXN],hy[MAXN],numm,numh;
     11 int g[MAXN][MAXN];
     12 int visx[MAXN],visy[MAXN],fx[MAXN],fy[MAXN],slack[MAXN],lk[MAXN];
     13 
     14 int Hungary_dfs(int u)
     15 {
     16     visx[u]=1;
     17     for (int i=1;i<=numm;i++)
     18     {
     19         int wt=fx[u]+fy[i]-g[u][i];
     20         if (!visy[i] && wt==0)
     21         {
     22             visy[i]=1;
     23             if (lk[i]==-1 || Hungary_dfs(lk[i]))
     24             {
     25                 lk[i]=u;
     26                 return 1;
     27             }
     28         }
     29         else if (wt<slack[i]) slack[i]=wt; 
     30     }
     31     return 0;
     32 }
     33 
     34 int KM()
     35 {
     36     memset(lk,-1,sizeof(lk));
     37     for (int i=1;i<=numm;i++)
     38     {
     39         fx[i]=-INF;
     40         fy[i]=0;
     41         for (int j=1;j<=numm;j++) fx[i]=max(fx[i],g[i][j]);
     42     }
     43     
     44     for (int i=1;i<=numm;i++)
     45     {
     46         memset(visx,0,sizeof(visx));
     47         memset(visy,0,sizeof(visy));
     48         memset(slack,127,sizeof(slack));//slack每次都要初始化为无穷大 
     49         while (!Hungary_dfs(i))
     50         {
     51             int delta=INF;
     52             for (int j=1;j<=numm;j++) if (!visy[j]) delta=min(delta,slack[j]);
     53             for (int j=1;j<=numm;j++)//这里忘掉了外面还套了一重循环,重复用了i! 
     54             {
     55                 if (visx[j])
     56                 {
     57                     visx[j]=0;
     58                     fx[j]-=delta;
     59                 } 
     60                 if (visy[j])
     61                 {
     62                     visy[j]=0;
     63                     fy[j]+=delta;
     64                 }
     65             }
     66         }
     67     }
     68     
     69     int ret=0; 
     70     for (int i=1;i<=numm;i++) ret+=fx[i]+fy[i];//这里numm写成了n 
     71     return ret;
     72 }
     73 
     74 void init()
     75 {
     76     numm=numh=0;
     77     for (int i=0;i<n;i++)
     78     {
     79         char c;
     80         getchar();
     81         for (int j=0;j<m;j++)
     82         {
     83             scanf("%c",&c);
     84             if (c=='m') 
     85             {
     86                 mx[++numm]=i;
     87                 my[numm]=j;
     88             }
     89             else if (c=='H')
     90             {
     91                 hx[++numh]=i;
     92                 hy[numh]=j;
     93             } 
     94         }
     95     }
     96     for (int i=1;i<=numm;i++)
     97         for (int j=1;j<=numh;j++)
     98         {
     99             g[i][j]=-1*(abs(mx[i]-hx[j])+abs(my[i]-hy[j]));
    100         }
    101 }
    102 
    103 int main()
    104 {
    105     while (scanf("%d%d",&n,&m))
    106     {
    107         if (n==m && m==0) break;
    108         init();
    109         cout<<KM()*(-1)<<endl;
    110     }
    111     return 0;
    112 } 
  • 相关阅读:
    调试cuda程序一定要细心啊 不然一个bug会折腾你2天
    XML和实体类之间相互转换(序列化和反序列化)
    C#实现实体类和XML相互转换
    C#压缩打包文件例子
    通过锁字符串达到控制并发的效果C#
    巧用Ajax的beforeSend 提高用户体验
    HTML代码在线运行工具
    .NET使用ZXing.NET生成中间带图片和不带图片的二维码
    获取电脑硬件信息 (硬盘,cpu,内存等)
    C# http请求带请求头部分
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5357396.html
Copyright © 2011-2022 走看看