座位调整问题【解决思路及求证】
2010-12-02 16:45
901 查看
近来无聊,开始做ACM练练脑子,恰好看到百度竞赛的一道《座位调整》题目:
题目描述:
百度办公区里到处摆放着各种各样的零食。百度人力资源部的调研发现,员工如果可以在自己喜欢的美食旁边工作,工作效率会大大提高。因此,百度决定进行一次员工座位的大调整。
调整的方法如下:
1 . 首先将办公区按照各种零食的摆放分成 N 个不同的区域。(例如:可乐区,饼干区,牛奶区等等)。
2 . 每个员工对不同的零食区域有不同的喜好程度(喜好程度度的范围为 1 — 100 的整数, 喜好程度越大表示该员工越希望被调整到相应的零食区域)。
3 . 由于每个零食区域可以容纳的员工数量有限,人力资源部希望找到一个最优的调整方案令到总的喜好程度最大。
数据输入:
第一行包含两个整数 N , M ,( 1<=N , M<=300 )。分别表示 N 个区域和 M 个员工。
第二行是 N 个整数构成的数列 a ,其中 a[i] 表示第 i 个区域可以容纳的员工数, (1<=a[i]<=M , a[1]+a[2]+..+a
=M) 。
紧接着是一个 M*N 的矩阵 P , P ( i , j )表示第 i 个员工对第 j 个区域的喜好度。
答案输出:
对于每个测试数据,输出可以达到的最大的喜好程度。
输入样例
3 3
1 1 1
100 50 25
100 50 25
100 50 25
输出样例
175
数据解释:此数据只存在一种安排方法,三个员工分别安置在三个区域。最终的喜好程度为 100+50+25=175
想了想,得出如下C#程序(我是C#初学者):
using System;
using System.Collections.Generic;
namespace ACM_2
{
class Program
{
static void Main()
{
try
{
var program = new Program();
string inputLine1 = Console.ReadLine();
int areas = 0;
int staffs = 0;
if(inputLine1 != null)
{
areas = Int32.Parse(inputLine1.Split(' ')[0]);
staffs = Int32.Parse(inputLine1.Split(' ')[1]);
}
var matrix = new int[staffs, areas];
var limitMatrix = new int[areas];
string inputLine2 = Console.ReadLine();
if(inputLine2 != null)
{
//set the limit of each area
for (int x = 0; x < inputLine2.Split(' ').Length;x++ )
{
limitMatrix[x] = Int32.Parse(inputLine2.Split(' ')[x]);
}
for (int i = 0; i < staffs; i++)
{
string loveAreas = Console.ReadLine();
if (loveAreas != null)
{
if (loveAreas.Split(' ').Length != areas)
{
Console.Error.WriteLine("Num of areas error in staffs.");
}
else
{
string[] love = loveAreas.Split(' ');
for (int j = 0; j < love.Length; j++)
{
matrix[i, j] = Int32.Parse(love[j]);
}
}
}
}
// now have got all the values in the matrix, start to caculate
// for each areas
var maxChoose = new int[areas];
for (int j = 0; j < areas;j++ )
{
var staffList = new List<bool>();
for (int i = 0; i < staffs;i++ )
{
staffList.Add(false);
}
var selected = new int[areas];
// for each loop,initual the marked list of each staff member
int firstStaff = program.GetLocalMaxStaff(staffList, matrix, staffs, areas, j);
maxChoose[j] = matrix[firstStaff,j];
program.MarkedAfterChoose(ref selected,ref staffList,j,firstStaff);
for (int l = 0; l < staffs -1;l++ )
{
// store the max matrix value in this circle
int max = 0;
int areaNo = -1;
int staffNo = -1;
for (int k = 0; k < areas; k++)
{
//get the max permitted staff in appointed area
if (selected[k] < limitMatrix[k])
{
// compare first,not real choose
int localStaff = program.GetLocalMaxStaff(staffList, matrix, staffs, areas, k);
int areaMax = matrix[localStaff, k];
if (areaMax > max)
{
max = areaMax;
areaNo = k;
staffNo = localStaff;
}
}
}
// after compare all of the max value, choose the best one and marked
program.MarkedAfterChoose(ref selected,ref staffList,areaNo,staffNo);
maxChoose[j] += max;
}
}
int finalMax = -1;
foreach (int t in maxChoose)
{
if(t>finalMax)
{
finalMax = t;
}
}
Console.WriteLine("Max Value:{0}",finalMax);
Console.ReadLine();
}
}catch(Exception e)
{
Console.Error.WriteLine(e.Message);
}
}
/// <summary>
/// when chosen,mark the status
/// </summary>
/// <param name="selected"></param>
/// <param name="staffList"></param>
/// <param name="areaNo"></param>
/// <param name="staff"></param>
public void MarkedAfterChoose(ref int[] selected, ref List<bool> staffList, int areaNo,int staff)
{
selected[areaNo]++;
staffList[staff] = true;
}
/// <summary>
/// get local max of each area
/// </summary>
/// <param name="staffList"></param>
/// <param name="matrix"></param>
/// <param name="staffs"></param>
/// <param name="areas"></param>
/// <param name="areaNo"></param>
/// <returns></returns>
public int GetLocalMaxStaff(List<bool>staffList,int[,] matrix,int staffs,int areas,int areaNo)
{
int max = 0;
int staff = -1;
for(int i= 0; i< staffs;i++)
{
if(!staffList[i] && matrix[i,areaNo] > max)
{
max = matrix[i, areaNo];
staff = i;
}
}
return staff;
}
}
}
跑了几个测试用例,好像都能通过,程序算法描述如下:
1、以每个AREA为分割进行几次独立的筛选,从喜好程序最大的人员进行选择,并将已被选择的人员进行标记以免下次被重复选择。
2、对于每次独立的筛选,分为M(员工人数)轮选择,以达到所有的员工都能对号入座。
3、对于每次独立筛选的每一轮,分为N(区域数目)种情况,每种情况代表从不同的AREA进行选择(AREA考虑容纳人数的限制,如果该AREA容纳人数已满,即selected[k] = limitMatrix[k]时,跳过该区域),每一轮结束取最大值,抛弃其它值。
4、所有独立筛选完成后,取最大值,即为最终最大值,抛弃其它值。
以下我的测试用例:
CASE 1:
3 3
1 1 1
100 50 25
100 50 25
100 50 25
CASE 2:
3 4
1 2 1
100 50 25
50 25 100
25 100 50
100 100 100
CASE 3:
3 3
1 1 1
100 99 1
1 50 45
9 10 1
CASE 4:
3 3
1 1 1
100 50 80
100 70 30
50 100 30
用例都能通过,但我对这种算法还是存在疑问,我的算法都是从最大值开始取,那么如果存在这么一种情况:【当所有的区域都未取最大值时,所得最后结果为最大值】,那我的算法就是错误的,求证!
题目描述:
百度办公区里到处摆放着各种各样的零食。百度人力资源部的调研发现,员工如果可以在自己喜欢的美食旁边工作,工作效率会大大提高。因此,百度决定进行一次员工座位的大调整。
调整的方法如下:
1 . 首先将办公区按照各种零食的摆放分成 N 个不同的区域。(例如:可乐区,饼干区,牛奶区等等)。
2 . 每个员工对不同的零食区域有不同的喜好程度(喜好程度度的范围为 1 — 100 的整数, 喜好程度越大表示该员工越希望被调整到相应的零食区域)。
3 . 由于每个零食区域可以容纳的员工数量有限,人力资源部希望找到一个最优的调整方案令到总的喜好程度最大。
数据输入:
第一行包含两个整数 N , M ,( 1<=N , M<=300 )。分别表示 N 个区域和 M 个员工。
第二行是 N 个整数构成的数列 a ,其中 a[i] 表示第 i 个区域可以容纳的员工数, (1<=a[i]<=M , a[1]+a[2]+..+a
=M) 。
紧接着是一个 M*N 的矩阵 P , P ( i , j )表示第 i 个员工对第 j 个区域的喜好度。
答案输出:
对于每个测试数据,输出可以达到的最大的喜好程度。
输入样例
3 3
1 1 1
100 50 25
100 50 25
100 50 25
输出样例
175
数据解释:此数据只存在一种安排方法,三个员工分别安置在三个区域。最终的喜好程度为 100+50+25=175
想了想,得出如下C#程序(我是C#初学者):
using System;
using System.Collections.Generic;
namespace ACM_2
{
class Program
{
static void Main()
{
try
{
var program = new Program();
string inputLine1 = Console.ReadLine();
int areas = 0;
int staffs = 0;
if(inputLine1 != null)
{
areas = Int32.Parse(inputLine1.Split(' ')[0]);
staffs = Int32.Parse(inputLine1.Split(' ')[1]);
}
var matrix = new int[staffs, areas];
var limitMatrix = new int[areas];
string inputLine2 = Console.ReadLine();
if(inputLine2 != null)
{
//set the limit of each area
for (int x = 0; x < inputLine2.Split(' ').Length;x++ )
{
limitMatrix[x] = Int32.Parse(inputLine2.Split(' ')[x]);
}
for (int i = 0; i < staffs; i++)
{
string loveAreas = Console.ReadLine();
if (loveAreas != null)
{
if (loveAreas.Split(' ').Length != areas)
{
Console.Error.WriteLine("Num of areas error in staffs.");
}
else
{
string[] love = loveAreas.Split(' ');
for (int j = 0; j < love.Length; j++)
{
matrix[i, j] = Int32.Parse(love[j]);
}
}
}
}
// now have got all the values in the matrix, start to caculate
// for each areas
var maxChoose = new int[areas];
for (int j = 0; j < areas;j++ )
{
var staffList = new List<bool>();
for (int i = 0; i < staffs;i++ )
{
staffList.Add(false);
}
var selected = new int[areas];
// for each loop,initual the marked list of each staff member
int firstStaff = program.GetLocalMaxStaff(staffList, matrix, staffs, areas, j);
maxChoose[j] = matrix[firstStaff,j];
program.MarkedAfterChoose(ref selected,ref staffList,j,firstStaff);
for (int l = 0; l < staffs -1;l++ )
{
// store the max matrix value in this circle
int max = 0;
int areaNo = -1;
int staffNo = -1;
for (int k = 0; k < areas; k++)
{
//get the max permitted staff in appointed area
if (selected[k] < limitMatrix[k])
{
// compare first,not real choose
int localStaff = program.GetLocalMaxStaff(staffList, matrix, staffs, areas, k);
int areaMax = matrix[localStaff, k];
if (areaMax > max)
{
max = areaMax;
areaNo = k;
staffNo = localStaff;
}
}
}
// after compare all of the max value, choose the best one and marked
program.MarkedAfterChoose(ref selected,ref staffList,areaNo,staffNo);
maxChoose[j] += max;
}
}
int finalMax = -1;
foreach (int t in maxChoose)
{
if(t>finalMax)
{
finalMax = t;
}
}
Console.WriteLine("Max Value:{0}",finalMax);
Console.ReadLine();
}
}catch(Exception e)
{
Console.Error.WriteLine(e.Message);
}
}
/// <summary>
/// when chosen,mark the status
/// </summary>
/// <param name="selected"></param>
/// <param name="staffList"></param>
/// <param name="areaNo"></param>
/// <param name="staff"></param>
public void MarkedAfterChoose(ref int[] selected, ref List<bool> staffList, int areaNo,int staff)
{
selected[areaNo]++;
staffList[staff] = true;
}
/// <summary>
/// get local max of each area
/// </summary>
/// <param name="staffList"></param>
/// <param name="matrix"></param>
/// <param name="staffs"></param>
/// <param name="areas"></param>
/// <param name="areaNo"></param>
/// <returns></returns>
public int GetLocalMaxStaff(List<bool>staffList,int[,] matrix,int staffs,int areas,int areaNo)
{
int max = 0;
int staff = -1;
for(int i= 0; i< staffs;i++)
{
if(!staffList[i] && matrix[i,areaNo] > max)
{
max = matrix[i, areaNo];
staff = i;
}
}
return staff;
}
}
}
跑了几个测试用例,好像都能通过,程序算法描述如下:
1、以每个AREA为分割进行几次独立的筛选,从喜好程序最大的人员进行选择,并将已被选择的人员进行标记以免下次被重复选择。
2、对于每次独立的筛选,分为M(员工人数)轮选择,以达到所有的员工都能对号入座。
3、对于每次独立筛选的每一轮,分为N(区域数目)种情况,每种情况代表从不同的AREA进行选择(AREA考虑容纳人数的限制,如果该AREA容纳人数已满,即selected[k] = limitMatrix[k]时,跳过该区域),每一轮结束取最大值,抛弃其它值。
4、所有独立筛选完成后,取最大值,即为最终最大值,抛弃其它值。
以下我的测试用例:
CASE 1:
3 3
1 1 1
100 50 25
100 50 25
100 50 25
CASE 2:
3 4
1 2 1
100 50 25
50 25 100
25 100 50
100 100 100
CASE 3:
3 3
1 1 1
100 99 1
1 50 45
9 10 1
CASE 4:
3 3
1 1 1
100 50 80
100 70 30
50 100 30
用例都能通过,但我对这种算法还是存在疑问,我的算法都是从最大值开始取,那么如果存在这么一种情况:【当所有的区域都未取最大值时,所得最后结果为最大值】,那我的算法就是错误的,求证!
相关文章推荐
- Lowest Common Ancestor问题的解决思路
- SQL编程之小问题的解决思路
- SQLSERVER解决HOT PAGE问题的其中一个思路使用表分区
- 解决问题的思路-工作篇
- tomcat内存溢出问题解决思路
- 什么是解决问题的思路:超级客服实战
- 一个页面中多个window.onload = function(){}冲突问题解决思路
- Linux网络故障的解决问题的思路
- Consumer rebalance失败问题定位和解决思路
- 如何对gcc和g++版本进行调整选择,解决"未定义的引用"的问题
- Windows Phone中解决多模块多程序集之间相互循环引用的问题一种思路
- MySQL在并发场景下的问题及解决思路
- 性能测试常见问题解决思路
- 解决ubuntu无法调整和保存屏幕亮度的问题
- nf_conntrack: table full, dropping packet问题的解决思路
- 动态库打包相关问题的解决思路
- 解决问题的思路
- xml 解析错误:未找到元素 问题解决思路及办法
- 一个页面中多个window.onload = function(){}冲突问题解决思路
- 从别人解决问题的思路中得到进步