• uvalive 3276 The Great Wall Game


    题意:

    一个n * n的棋盘上放着n个棋子,现在要求把这n个棋子用最少的步数移到同一条直线上,即同一列同一行或者同一对角线(两条)。输出最少的步数(只能往四个方向移动,即正东,正西,正南,正北)。

    思路:

    每个棋子唯一对应一个格子,每个棋子不能在同一个格子,那么就相当于一个二分图(强行二分图)。

    因为n很小,所以可以枚举每一行,每一列,两条对角线,然后每个点移动到每一条直线的每一个格子都有一个距离,那么这个点就向格子连一条权值为距离的边,这个问题就转化成了求所有最佳完美的匹配中的最小值,用KM算法。

    因为我们求的是最小步数,所以求的是带权二分图的最小匹配

    求最小匹配,就将每一条边的权值取反,然后求最大匹配,再将最后的结果取反就得到了最小匹配的结果。

    复杂度为O(n^4)。

    注意:输出很坑,每一个答案后都有一个换行,并不是两个中间输出一个,也就是说,最后一个后面也有换行。

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <vector>
      5 using namespace std;
      6 
      7 const int N = 20;
      8 const int inf = 0x3f3f3f3f;
      9 
     10 int love[N][N];
     11 int lx[N],ly[N];
     12 bool visx[N],visy[N];
     13 int match[N];
     14 int slack[N];
     15 
     16 struct node
     17 {
     18     int x,y;
     19     
     20     node(int aa,int bb)
     21     {
     22         x = aa;
     23         y = bb;
     24     }
     25 };
     26 
     27 vector<node> vn;
     28 
     29 int mabs(int x)
     30 {
     31     return x >= 0 ? x : -x;
     32 }
     33 
     34 bool dfs(int u,int n)
     35 {
     36     visx[u] = 1;
     37     
     38     for (int i = 1;i <= n;i++)
     39     {
     40         if (visy[i]) continue;
     41         
     42         int gap = lx[u] + ly[i] - love[u][i];
     43         
     44         if (gap == 0)
     45         {
     46             visy[i] = 1;
     47             
     48             if (match[i] == -1 || dfs(match[i],n))
     49             {
     50                 match[i] = u;
     51                 return true;
     52             }
     53         }
     54         else
     55         {
     56             slack[i] = min(gap,slack[i]);
     57         }
     58     }
     59     
     60     return false;
     61 }
     62 
     63 int km(int n)
     64 {
     65     memset(match,-1,sizeof(match));
     66     memset(ly,0,sizeof(ly));
     67     
     68     for (int i = 1;i <= n;i++)
     69     {
     70         lx[i] = love[i][1];
     71         
     72         for (int j = 2;j <= n;j++)
     73         {
     74             lx[i] = max(lx[i],love[i][j]);
     75         }
     76     }
     77     
     78     for (int i = 1;i <= n;i++)
     79     {
     80         memset(slack,inf,sizeof(slack));
     81         
     82         while (1)
     83         {
     84             memset(visx,0,sizeof(visx));
     85             memset(visy,0,sizeof(visy));
     86             
     87             if (dfs(i,n)) break;
     88             
     89             int d = inf;
     90             
     91             for (int j = 1;j <= n;j++)
     92             {
     93                 if (!visy[j]) d = min(d,slack[j]);
     94             }
     95             
     96             for (int j = 1;j <= n;j++)
     97             {
     98                 if (visx[j]) lx[j] -= d;
     99                 
    100                 if (visy[j]) ly[j] += d;
    101             }
    102         }
    103 
    104     }
    105         
    106     
    107     int res = 0;
    108     
    109     for (int i = 1;i <= n;i++)
    110     {
    111         res += love[match[i]][i];
    112     }
    113     
    114     return res;
    115 }
    116 
    117 int main()
    118 {
    119     int n;
    120     int kase = 0;
    121     
    122     while (scanf("%d",&n) != EOF && n)
    123     {
    124         vn.clear();
    125         
    126         for (int i = 0;i < n;i++)
    127         {
    128             int a,b;
    129             
    130             scanf("%d%d",&a,&b);
    131             
    132             vn.push_back(node(a,b));
    133         }
    134         
    135         //if (kase) printf("
    ");
    136         
    137         int ans = 1e8;
    138         
    139         for (int i = 1;i <= n;i++)
    140         {
    141             for (int j = 0;j < vn.size();j++)
    142             {
    143                 for (int k = 1;k <= n;k++)
    144                 {
    145                     int dx = mabs(vn[j].x - i);
    146                     int dy = mabs(vn[j].y - k);
    147                     love[j+1][k] = -(dx + dy);
    148                 }
    149             }
    150             
    151             int tmp = -km(n);
    152             
    153             //printf("%d **
    ",tmp);
    154             
    155             ans = min(tmp,ans);
    156         }
    157         
    158         for (int i = 1;i <= n;i++)
    159         {
    160             for (int j = 0;j < vn.size();j++)
    161             {
    162                 for (int k = 1;k <= n;k++)
    163                 {
    164                     int dy = mabs(vn[j].y - i);
    165                     int dx = mabs(vn[j].x - k);
    166                     love[j+1][k] = -(dx + dy);
    167                 }
    168             }
    169             
    170             int tmp = -km(n);
    171             
    172             ans = min(tmp,ans);
    173             
    174             //printf("%d **
    ",tmp);
    175         }
    176         
    177         for (int i = 1;i <= n;i++)
    178         {
    179             for (int j = 0;j < vn.size();j++)
    180             {
    181                 int dx = mabs(vn[j].x - i);
    182                 int dy = mabs(vn[j].y - i);
    183                 
    184                 love[j+1][i] = -(dx + dy);
    185             }
    186         }
    187         
    188         ans = min(ans,-km(n));
    189         
    190         for (int i = 1;i <= n;i++)
    191         {
    192             for (int j = 0;j < vn.size();j++)
    193             {
    194                 int dx = mabs(vn[j].x - i);
    195                 int dy = mabs(vn[j].y - (n - i + 1));
    196                 
    197                 love[j+1][i] = -(dx + dy);
    198             }
    199         }
    200         
    201         ans = min(ans,-km(n));
    202         
    203         printf("Board %d: %d moves required.
    
    ",++kase,ans);
    204     }
    205     
    206     return 0;
    207 }
  • 相关阅读:
    PHP基础知识系列:预定义变量
    PHP基础知识系列:拦截器方法
    【PHP设计模式】创建型之单例(Singleton)
    PHP基础知识系列:cookie与session
    select问题
    柳传志给杨元庆的信
    PHP基础知识系列:多态性
    PHP基础知识系列:面向对象基础
    PHP处理字符串翻转问题总结
    PHP基础知识系列:静态
  • 原文地址:https://www.cnblogs.com/kickit/p/8809138.html
Copyright © 2020-2023  润新知