呃,这题也太坑人了吧,受不了了~~ 本来想练练自己的代码正确率的,结果一上午就这样的浪费在这道题上了,伤心了,呜呜~~
首先,是这题的输入格式,做之前看了discuss,知道输入的两个矩阵是相反的,所以并没有在这上面浪费多长时间。然后是输出格式,本来想用一个link数组记录下最优匹配就好了,不由深搜,后来才明白,原来题目是让输出所有符合要求的匹配方式,而用数组记录的只是其中一个,最后,最后,就卡死在了一个点上,直到现在还是不明白为什么那样写是错的,感觉没什么大影响啊~恳求哪位大牛能给与指导~~还有一点就是,这题权值搜索要用负值,如果用正的会超时~~
好吧,下面贴出代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <iostream> #define maxx 20 #define INF 0xffffff using namespace std; int mm[maxx][maxx] ; int vistx[maxx] , visty[maxx] ; int lx[maxx] , ly[maxx] ; int linkx[maxx] ; int mark[maxx] , f[maxx] ; int n , s , sum , minn ; int find ( int x ) { int i ; vistx[x] = 1; for ( i = 1 ; i <= n ; i++ ) if ( !visty[i] ) { int t = lx[x] + ly[i] - mm[x][i] ; if ( t == 0 ) { visty[i] = 1; if ( linkx[i] == 0 || find ( linkx[i] )) { linkx[i] = x; return 1; } } else if ( minn > t ) minn = t ; } return 0; } int KM () { int i , j , k ; memset( lx , 0 , sizeof ( lx )); memset( ly , 0 , sizeof ( ly )); memset( linkx , 0 , sizeof ( linkx )); for ( i = 1 ; i <= n ; i++ ) for ( j = 1 ; j <= n ; j++ ) if ( lx[i] < mm[i][j] ) lx[i] = mm[i][j]; for ( i = 1; i <= n ; i++ ) { while ( 1 ) { memset( vistx , 0 , sizeof ( vistx ));//呃,就是卡死在这里了,将这两个初始化语句放在while memset( visty , 0 , sizeof ( visty ));//里面就对,放到外面就WA了,不知道为什么,这有什么影响吗?? minn = INF ; if ( find ( i )) break; for ( j = 1; j <= n ; j++ ) { if ( vistx[j] ) lx[j] -= minn ; if ( visty[j] ) ly[j] += minn ; } } } int ss = 0; for ( i = 1 ; i <= n ; i++ ) if ( linkx[i] ) ss += mm[linkx[i]][i]; return ss; } void dfs ( int step , int ans )//深搜输出所有可能的最优匹配 { int i ; if ( ans > sum ) return ; if ( step >n ) { if ( ans != sum ) return ; else { printf ( "Best Pairing %d\n" , s++ ); for ( i = 1 ; i <= n ; i++ ) printf ( "Supervisor %d with Employee %d\n" , i , mark[i] ); return ; } } else { for ( i = 1 ; i <= n ; i++ ) if ( !f[i] ) { f[i] = 1; mark[step] = i ; dfs ( step+1 , ans - mm[step][i] ); f[i] = 0; } } } int main() { int cas , i , j , k , x; scanf ( "%d" , &cas ); for ( k = 1 ; k <= cas ; k++ ) { scanf ( "%d" , &n ); memset( mm , 0 , sizeof ( mm )); for ( i = 1 ; i <= n ; i++ ) for ( j = 1 ; j <= n ; j++ ) { scanf ( "%d" , &x ); mm[x][i] -= ( j - 1 );//数组要用负值,否则会超时 } for ( i = 1 ; i <= n ; i++ ) for ( j = 1 ; j <= n ; j++ ) { scanf ( "%d" , &x ); mm[i][x] -= ( j - 1 ); } sum = -KM(); printf ( "Data Set %d, Best average difference: %.6lf\n", k , sum / ( 2.0 * n )); s = 1; memset( mark , 0 , sizeof ( mark )); memset( f , 0 , sizeof ( f )); dfs( 1 , 0 ); printf ( "\n" ); } return 0; }