百度之星2006年初赛 座位调整

来源:互联网 发布:java offsetdatetime 编辑:程序博客网 时间:2024/04/29 03:28
 

 1366:座位调整

Time Limit:1000MS  Memory Limit:65536K
Total Submit:3 Accepted:2 Page View:20

[Submit]   [Status]   [Discuss]

Font Size:AaAaAa

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 31 1 1100 50 25100 50 25100 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 305using 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;}

原创粉丝点击