座位调整问题【解决思路及求证】

这是一篇关于ACM竞赛中一道名为《座位调整》的题目解析,主要涉及如何将员工分配到他们喜欢的零食区域以最大化总体喜好程度。文章提供了C#程序实现,通过按区域独立筛选并选择喜好程度最高的员工,但作者对仅从最大值开始取是否能得到最优解提出疑问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

近来无聊,开始做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[N]=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

 

用例都能通过,但我对这种算法还是存在疑问,我的算法都是从最大值开始取,那么如果存在这么一种情况:【当所有的区域都未取最大值时,所得最后结果为最大值】,那我的算法就是错误的,求证!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值