程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu1350解題報告-最小邊覆蓋

hdu1350解題報告-最小邊覆蓋

編輯:C++入門知識

題意:一個出租車公司有M個預約,每個預約的信息占據一行:(如下例)   08:23  a  b  c  d   (a,b)表示這個預約的起點,(c,d)表示這個任務的終點,前面的時間便是開始的時間,那這個任務結束的時間是|a-c|+|b-d| + 開始的時間,那麼對於這M個預約,問最少派多少輛車就可以全部完成?   分析:開始我想到的是貪心算法中的時間調度問題,但是後面發現錯啦,這裡我們應該是用到二分匹配的最小邊覆蓋,對於最小邊覆蓋有如下:     最小路徑覆蓋=|P|-最大匹配數(|P|為定點數) 其中最大匹配數的求法是把P中的每個頂點pi分成兩個頂點pi'與pj'',如果在p中存在一條pi到pj的邊,那麼在二分圖P'中就有一條連接pi'與pj''的無向邊;這裡pi' 就是p中pi的出邊,pj''就是p中pj 的一條入邊; 對於公式:最小路徑覆蓋=|P|-最大匹配數;可以這麼來理解; 如果匹配數為零,那麼P中不存在有向邊,於是顯然有: 最小路徑覆蓋=|P|-最大匹配數=|P|-0=|P|;即P的最小路徑覆蓋數為|P|; P'中不在於匹配邊時,路徑覆蓋數為|P|; 如果在P'中增加一條匹配邊pi'-->pj'',那麼在圖P的路徑覆蓋中就存在一條由pi連接pj的邊,也就是說pi與pj 在一條路徑上,於是路徑覆蓋數就可以減少一個; 那麼可以這樣解決: 我們把所有的任務看成點,那麼如果完成第 i 個任務還能完成第 j 個任務,我們就加一條邊 i-->j,那麼有一個地方值得注意的是:在計算完成i 能否完成j的時候,我們應該是這樣的判斷條件:     [cpp]   if(node[i].st >= node[j].end + 1+ abs(node[i].a-node[j].c) + abs(node[i].b-node[j].d) )   {       add(i,j);   }   對於判斷條件解釋為:完成第 i 個任務,我們所在地點是 (node[i].c,node[i].d)這個地點,那麼我們到達 j 任務的起點處的時間為: [cpp]  abs(node[i].a-node[j].c) + abs(node[i].b-node[j].d)   那麼整個題目就分析完畢,上馬:   [cpp]  // 265MS 996K    #include<stdio.h>   #include<math.h>   #include<string.h>      #define MAX 505      int N;   struct Node   {       int st,end;       int a,b,c,d;   }node[MAX];      struct Edge   {       int to,nxet;   }edge[MAX*MAX];   int head[MAX],tol;      void add(int a,int b)   {       edge[tol].to = b;       edge[tol].nxet = head[a];       head[a] = tol ++;   }      int link[MAX],vis[MAX];      bool dfs(int u)   {       for(int j = head[u]; j != -1; j=edge[j].nxet)       {           int v = edge[j].to;           if(vis[v]) continue;           vis[v] = true;           if( link[v] == -1 || dfs(link[v]))           {               link[v] = u;return true;           }       }       return false;   }      int match()   {       int ans=0;       memset(link,-1,sizeof(link));       for(int i = 1; i <= N; i ++)       {           memset(vis,0,sizeof(vis));           if(dfs(i)) ans++;       }       return ans;   }      int main ()   {       int T;       int h,m;       scanf("%d",&T);       while(T -- )       {           tol = 0;           memset(head,-1,sizeof(head));           scanf("%d",&N);           for(int i = 1; i <= N; i ++)           {               scanf("%d:%d",&h,&m);               scanf("%d%d%d%d",&node[i].a,&node[i].b,&node[i].c,&node[i].d);               node[i].st = h*60+m;               node[i].end = node[i].st+abs(node[i].a-node[i].c)+abs(node[i].b-node[i].d);               for(int j = i-1; j > 0 ; j --)               {                   if(node[i].st >= node[j].end + 1+ abs(node[i].a-node[j].c) + abs(node[i].b-node[j].d) )                   {                       add(i,j);                   }               }           }           printf("%d\n",N-match());       }       return 0;   }   個人愚昧觀點,歡迎指正與討論

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved