zoukankan      html  css  js  c++  java
  • hdu 4862 jump 最小k路径覆盖 km算法 建模

    【题意】:给你一个n*m的矩阵,填充着0-9的数字,每次能从一个点出发,到它的右边或者下边的点,花费为|x1-x2|+|y1-y2|-1,    

                   如果跳跃的起点和终点的数字相同,则获得这个数字的收益,不能走已经走过的点

                   有K次重新选择起点的机会

                   如果可以走遍所有点,则输出最大的价值(收益-花费),否则,输出-1

    【思路】当二部图里的两部分子集相同的时候可以用km来求路径(路径没有重边和重复的点)和连通性。1配2   2配3  3配4 代表的就是路径1->2>3-> 4  所以关键就是建模了。

                 

                 1.若点i 点j可以直接到达,就在i,j之间建边权值为:得到的能量-消耗的;

                 2.再增加k个点 同每一个点建边 权值为0,表示有K次重新选择起点的机会,每次可以可以从任意一个点开始;

                 3.同时每个点也分别和这k个点建边 权值为0 表示一次可以只选一个点  ;

                 4.新增的点和自己有一条连边权值为0 表示放弃这次 重新选起点的机会。

    用km 算法求得的权值和<0 说明没有完美匹配(不能在k次以内完全覆盖)输出-1 ,否则输出结果。

      1 #include<iostream>
      2 #include<vector>
      3 #include<string.h>
      4 #include<queue>
      5 #include<math.h>
      6 #include<stdio.h>
      7 #define INF 9999999
      8 using namespace std;
      9 #define maxx 220
     10 int link[maxx],lx[maxx],ly[maxx],w[maxx][maxx];
     11 bool s[maxx],t[maxx];
     12 char str[maxx][maxx];
     13 
     14 void init(int n)
     15 {
     16     for(int i=0; i<n; i++)
     17         for(int j=0; j<n; j++)
     18             w[i][j]=-INF;
     19 }
     20 
     21 void add(int s,int t,int c)
     22 {
     23     w[s][t]=c;
     24 }
     25 
     26 int dfs(int x,int n)
     27 {
     28     s[x]=true;
     29     for(int i=0; i<n; i++)
     30         if(t[i]==false&&lx[x]+ly[i]==w[x][i])//&&w[x][i]!=-INF
     31         {
     32             t[i]=true;
     33             if(link[i]==-1||dfs(link[i],n))
     34             {
     35                 link[i]=x;
     36                 return 1;
     37             }
     38         }
     39     return 0;
     40 }
     41 
     42 void update(int n)
     43 {
     44     int a=INF;
     45     for(int i=0; i<n; i++)
     46         if(s[i])
     47             for(int j=0; j<n; j++)
     48                 if(!t[j])
     49                     a=min(a,lx[i]+ly[j]-w[i][j]);
     50     for(int i=0; i<n; i++)
     51     {
     52         if(s[i]) lx[i]-=a;
     53         if(t[i]) ly[i]+=a;
     54     }
     55 }
     56 
     57 int km(int n)
     58 {
     59     bool flag=false;
     60     memset(link,-1,sizeof(link));
     61     for(int i=0; i<n; i++)
     62     {
     63         lx[i]=ly[i]=0;
     64         for(int j=0; j<n; j++)
     65             lx[i]=max(lx[i],w[i][j]);
     66     }
     67     for(int i=0; i<n; i++)
     68     {
     69         while(1)
     70         {
     71             memset(s,false,sizeof(s));
     72             memset(t,false,sizeof(t));
     73             if(dfs(i,n))
     74                 break;
     75             else update(n);
     76         }
     77     }
     78     int ans=0;
     79     for(int i=0; i<n; i++)
     80         ans+=w[link[i]][i];
     81     return ans;
     82 
     83 }
     84 
     85 int main()
     86 {
     87     int i,j,n,m,t,k,cas=1;
     88     scanf("%d",&t);
     89     while(t--)
     90     {
     91         scanf("%d%d%d",&n,&m,&k);
     92         for(int i=0; i<n; i++)
     93             scanf("%s",str[i]);
     94         init(n*m+k);
     95         for(int i=0; i<n; i++)
     96             for(int j=0; j<m; j++)
     97             {
     98                 for(int p=i+1; p<n; p++)
     99                 {
    100                     int temp=0;
    101 
    102                     if(str[i][j]==str[p][j])
    103                         temp=str[i][j]-'0';
    104                     temp-=(p-i-1);
    105 
    106                     add(i*m+j,p*m+j,temp);            // 1
    107                 }
    108                 for(int q=j+1; q<m; q++)
    109                 {
    110                     int temp=0;
    111 
    112                     if(str[i][j]==str[i][q])
    113                         temp=str[i][j]-'0';
    114                     temp-=(q-j-1);
    115 
    116                     add(i*m+j,i*m+q,temp);              //  1
    117                 }
    118             }
    119         for(int p=n*m; p<n*m+k; p++) //  X中新增的k个点
    120         {
    121             for(int i=0; i<n; i++)
    122                 for(int j=0; j<m; j++)
    123                     {
    124                         add(i*m+j,p,0);             //  2
    125                         add(p,i*m+j,0);            //  3
    126                     }
    127             add(p,p,0);                          //4
    128         }
    129         printf("Case %d : ",cas++);
    130         int ans;
    131         ans=km(n*m+k);
    132         if(ans<0)
    133             printf("-1
    ");
    134         else
    135             printf("%d
    ",ans);
    136     }
    137 
    138 }
  • 相关阅读:
    Diablo3 英雄榜-显示用户的装备信息-Volley读取API的图片资源,使用MySingleton管理RequestQueue
    Diablo3英雄榜-使用Volley和Gson来处理暴雪API的Json数据
    Diablo3英雄榜-API分析
    《Android编程权威指南》-读书笔记(十一) 完善CriminalIntent
    《Android编程权威指南》-读书笔记(十)-从一个内涵段子开始第二个例子
    さらば、博客园よ
    Kotlin有点用力过猛了
    记一个耻辱
    备份一个省市区JSON数据
    博(wǒ)客(zì)园(jǐ)的排版真是丑毙了
  • 原文地址:https://www.cnblogs.com/assult/p/3893934.html
Copyright © 2011-2022 走看看