同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。
说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
输入
第一行有两个m,n,表示技术人员数与顾客数。
接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。
输出
最小平均等待时间,答案精确到小数点后2位。
样例
repair.in
2 2
3 2
1 4
repair.out
1.50
数据范围:
(2<=M<=9,1<=N<=60), (1<=T<=1000)
就是拆个点 ,很套路的题 ,qwq 。
将每个工人拆成n*m个点 ,表示该工人第i时刻的修第j个人的车,而它只会对后面的值产生影响 , 所有直接*k(k表示还有多少人没修) 。
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cstdio> 5 #include <queue> 6 const int inf = 1 << 30 , maxn = 605 ; 7 using namespace std ;//1061109567 8 int m , n , head[maxn] , a[65][11] , dis[maxn] , s ,t ,ans , cnt ; 9 bool mark[maxn] ; 10 struct id 11 { 12 int to , nxt , val , vol ; 13 } edge[100001] ; 14 queue< int > Q ; 15 16 inline void Init ( ) 17 { 18 freopen( "NSOOJ#10395.in" , "r" , stdin ) ; 19 freopen( "NSOOJ#10395.out" , "w" , stdout ) ; 20 } 21 22 int read( ) 23 { 24 char ch = getchar( ) ; int k = 1 , ret = 0 ; 25 while( ch < '0' || ch > '9' ) { if( ch == '-' ) k = -1 ; ch = getchar( ) ; } 26 while( ch >= '0' && ch <= '9' ) ret = ret * 10 + ch - '0' , ch = getchar( ) ; 27 return k * ret ; 28 } 29 30 void add( int u , int v , int va , int vo ) 31 { 32 edge[++cnt].nxt = head[u] , edge[cnt].to = v ; 33 edge[cnt].val = va , edge[cnt].vol = vo , head[u] = cnt ; 34 } 35 36 void input( ) 37 { 38 m = read( ) , n = read( ) ; 39 int now = m * n ; cnt = -1 ; 40 s = 0 , t = now + n + 1 ; 41 memset( head , -1 , sizeof(head) ) ; 42 for( int x = 1 ; x <= n ; ++x ) 43 for( int y = 1 ; y <= m ; ++y ) 44 a[x][y] = read( ) ; 45 46 for( int i = 1 ; i <= now ; i++ ) 47 { 48 add( s , i , 1 , 0 ) ; 49 add( i , s , 0 , 0 ) ; 50 } 51 for( int i = now + 1 ; i <= now + n ; ++i ) 52 { 53 add( i , t , 1 , 0 ) ; 54 add( t , i , 0 , 0 ) ; 55 } 56 for( int i = 1 ; i <= m ; ++i ) 57 for( int j = 1 ; j <= n ; ++j ) 58 for( int k = 1 ; k <= n ; ++k ) 59 { 60 add( (i-1)*n+j , k+now , 1 , a[k][i]*j ) ; 61 add( k+now , (i-1)*n+j , 0 , 0-(a[k][i]*j) ) ; 62 } 63 } 64 65 bool spfa( ) 66 { 67 memset( mark , 0 , sizeof(mark) ) ; 68 memset( dis , 127/2 , sizeof(dis) ) ; 69 mark[t] = 1 ; dis[t] = 0 ; Q.push( t ) ; 70 while( !Q.empty( ) ) 71 { 72 int u = Q.front( ) ; Q.pop( ) ; 73 for( int i = head[u] ; ~i ; i = edge[i].nxt ) 74 { 75 76 int v = edge[i].to ; 77 if( edge[i^1].val && dis[v] > dis[u] + edge[i^1].vol ) 78 { 79 dis[v] = dis[u] + edge[i^1].vol ; 80 if( !mark[v] ) 81 { 82 mark[v] = 1 ; 83 Q.push( v ) ; 84 } 85 } 86 87 } 88 mark[u] = false ; 89 } 90 return dis[0] != 1061109567 ; 91 } 92 93 94 int dfs( int u , int f ) 95 { 96 mark[u] = true ; 97 if( u == t ) return f ; 98 int w , used = 0 ; 99 for( int i = head[u] ; ~i ; i = edge[i].nxt ) 100 { 101 int v = edge[i].to ; 102 if( dis[v] == dis[u] - edge[i].vol && edge[i].val && !mark[v] ) 103 { 104 w = f - used ; 105 w = dfs( v , min( w , edge[i].val ) ) ; 106 ans += w * edge[i].vol ; 107 edge[i].val -= w , edge[i^1].val += w ; used += w ; 108 if( used == f ) return used ; 109 } 110 } 111 return used ; 112 } 113 114 115 void zkw( ) 116 { 117 int sum = 0 ; 118 while( spfa( ) ) 119 { 120 mark[t] = 1 ; 121 while( mark[t] ) 122 { 123 memset( mark , 0 , sizeof(mark) ) ; 124 sum = dfs( s , inf ) ; 125 } 126 } 127 printf( "%.2f " , (double)ans/n ) ; 128 } 129 130 131 int main( ) 132 { 133 // Init( ) ; 134 input( ) ; 135 zkw( ) ; 136 // fclose( stdin ) ; 137 // fclose( stdout ) ; 138 return 0 ; 139 }