分支限界求任務分配
2010/05/15 下午 09:04
題目:
只有一組測試案例。
輸入:第一行是操作員的人數n(4=<n<=9),接下來的n行裡每行有n個數,分別表示第i名操作員完成第i項任務的時間。
輸出:完成所有任務的最短時間。
輸入樣本:
4
3 8 4 12
9 12 13 5
8 7 9 3
12 7 6 8
輸出樣本:
21
要求:資料結構必須採用堆。
解題思路
這題說是要用堆來做,其實是把問題複雜化了,用動態規劃很快就能做出來
#include <iostream>using namespace std;int n,c[1000][1000],a[1000],best=30000,sum;void find(int i){int j,temp;if(i==n){ if(sum<best) best=sum;}else{ for(j=i;j<n;j++) { temp=a[j]; a[j]=a[i]; a[i]=temp; sum+=c[a[i]][i]; if(sum<=best ) find(i+1); sum-=c[a[i]][i]; temp=a[j]; a[j]=a[i]; a[i]=temp; }}}int main(){int i,j;cin>>n;for(i=0;i<n;i++) for(j=0;j<n;j++) cin>>c[i][j];//i為工作for(i=0;i<n;i++) a[i]=i;find(0);cout<<best<<endl;return 0;}
其實這題還可以用二分圖來做,我沒有按照老師的要求用堆,而是用的二分圖,如果不懂二分圖,建議去看一下,雖然不可能經常用到,但一旦用到,對解題還是很有協助的。此題其實就是一個最優匹配而已。
#include<iostream>using namespace std;int n, m;int map[15][15];int lx[15],ly[15];int mat[15];bool vx[15],vy[15];bool dfs(int u){vx[u] = true;for(int v=0; v<n; v++){ if(!vy[v] && lx[u]+ly[v] == map[u][v]) { vy[v] = true; if(mat[v]==-1 || dfs(mat[v])) { mat[v] = u; return true; } }}return false;}int main(){cin>>n;int i,j,u,v;for( i=0;i<n;i++) for( j=0;j<n;j++) { cin>>map[i][j]; } for( i=0;i<n;i++) for( j=0;j<n;j++) { map[i][j]=200-map[i][j]; } for( u=0;u<n;u++) lx[u]=-0x1fffffff; memset(ly, 0, sizeof(ly)); for( u=0; u<n; u++) for( v=0; v<n; v++) lx[u] = max(lx[u], map[u][v]); memset(mat, -1, sizeof(mat)); for( u=0; u<n; u++) { while(1) { memset(vx, 0, sizeof(vx)); memset(vy, 0, sizeof(vy)); if(dfs(u)) break; int al = INT_MAX; for(i=0; i<n; i++) { if(vx[i]) { for( j=0;j<n;j++) { if(!vy[j]) { al = min(al, lx[i]+ly[j]-map[i][j]); } } } } for( i=0; i<n; i++) { if(vx[i]) lx[i] -= al; if(vy[i]) ly[i] += al; } } } int res = 0; for( v=0; v<n; v++) res += 200-map[mat[v]][v]; cout<<res<<endl; return 0;}