1366:座位调整
Time Limit:1000MS Memory Limit:65536K
Total Submit:3 Accepted:2 Page View:20
Description
百度办公区里到处摆放着各种各样的零食。百度人力资源部的调研发现,员工如果可以在自己喜欢的美食旁边工作,效率会大大提高。因此,百度决定进行一次员工座位的大调整。 调整的方法如下: 1.首先将办公区按照各种零食的摆放分成N个不同的区域(例如:可乐区,饼干区,牛奶区等等); 2.每个员工对不同的零食区域有不同的喜好程度(喜好程度是1~100的整数, 喜好程度越大表示该员工越希望被调整到相应的零食区域); 3.由于每个零食区域可以容纳的员工数量有限,人力资源部希望找到一个最优的调整方案使得总的喜好程度最大。
Input
第一行包含两个整数N,M(N>=1,M<=300)。分别表示N个区域和M个员工; 第二行是N个整数构成的数列a,其中a[i]表示第i个区域可以容纳的员工数(1<=a[i]<=M,a[1]+a[2]+...+a[N]=M); 紧接着是一个M*N的矩阵P,P(i,j)表示第i个员工对第j个区域的喜好程度.
Output
对于每个测试数据,输出可以达到的最大的喜好程度。
Sample Input
3 3 1 1 1 100 50 25 100 50 25 100 50 25
Sample Output
175
Hint
此数据只存在一种安排方法,三个员工分别安置在三个区域。最终的喜好程度为100+50+25=175
Source
Astar2006 初赛
做法就是KM算法
我的建图过程如下: 把食品供应点拆开,不要让他成为一个点,如果一个食品供应点能够供应2个人,那就把它拆开成两个点,由于食品供应点的所有人数之和是等于员工数的,所以刚好构成一个两边点数一样的一个二分图,然后从员工到供应点连边的边权就是喜好度,然后再用KM算法进行最大带权匹配就好了,最后建的图是一个M*M的矩阵,由于M小于300,所以KM算法能够过。
也见到过别人用DP过掉的,不过没有想通。。DP一直很弱。。
话说我已经退役了,这个博客很少用了。。
#include<stdio.h> #include<algorithm> #include<string.h> #define inf 99999999 #define maxn 305 using namespace std; int n,m; int a[maxn]; int map[maxn][maxn]; int temp[maxn][maxn]; int link[maxn]; int lx[maxn],ly[maxn]; bool x[maxn],y[maxn]; bool dfs(int u) { int i; x[u]=true; for(i=1;i<=n;i++) { if(lx[u]+ly[i]==map[u][i]&&!y[i]) { y[i]=true; if(link[i]==-1||dfs(link[i])) { link[i]=u; return true; } } } return false; } int main() { int i,j,k,num; while(scanf("%d%d",&m,&n)!=EOF) { for(i=1;i<=m;i++) scanf("%d",&a[i]); for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%d",&temp[i][j]); for(i=1;i<=n;i++) { num=0; for(j=1;j<=m;j++) { for(k=1;k<=a[j];k++) { num++; map[i][num]=temp[i][j]; } } } memset(x,0,sizeof(x)); memset(y,0,sizeof(y)); memset(link,-1,sizeof(link)); memset(ly,0,sizeof(ly)); for(i=0;i<maxn;i++) lx[i]=inf; for(k=1;k<=n;k++) { while(1) { memset(x,0,sizeof(x)); memset(y,0,sizeof(y)); if(dfs(k)) break; int d=inf; for(i=1;i<=n;i++) if(x[i]) for(j=1;j<=n;j++) if(!y[j]&&lx[i]+ly[j]-map[i][j]<d) d=lx[i]+ly[j]-map[i][j]; for(i=1;i<=n;i++) if(x[i]) lx[i]=lx[i]-d; for(i=1;i<=n;i++) if(y[i]) ly[i]=ly[i]+d; } } int ans1=0,ans2=0; for(i=1;i<=n;i++) ans1=ans1+map[link[i]][i]; printf("%d\n",ans1); } return 0; }