1021 社区很忙(难倒很多聪明人的一道题)

题目详情

未来的某一年开始,很多创业团队开始在CSDN社区内办公,社区每年会组织同学与项目的双选会,即入职者与各个创业项目(团队)相互挑选,假设现在有M个项目,编号从1到M,另有N名同学,编号从1到N,每名同学能选择最多三个、最少一个感兴趣的项目。选定之后,HR会安排项目负责人和相应感兴趣的同学一对一面谈,每次面谈持续半小时。由于大家平时都很忙,所以咱们要尽量节约时间,请你按照以下的条件设计算法,帮助HR安排面试:

1)同学很忙。项目负责人一次只能与一名同学面谈,而同学会在自己第一个面试开始时达到社区,最后一个面试结束后离开社区,如果参加一个项目组的面试后不能立即参加下一个项目组的面试,就必须在社区等待。所以请尽可能让同学的面试集中在某一时间段,减少同学在社区等待的时间。
2)项目负责人很忙。众所周知,创业团队的负责人会有很多事情要做,所以他们希望能够将自己参与的面试集中在某一段时间内,请在保证1)的情况下,使得项目负责人等待的时间最少。
3)HR很忙。从第一轮面试开始以后,所有HR都必须等到最后一轮面试结束,所以需要在保证1)和2)的同时,也能尽快解放掉所有的HR,即让第一轮面试到最后一轮面试之间持续的时间最短。

输入(以文件方式输入,文件名为iw,例如iw.in):
    第1行...第n行:同学的编号 项目的编号
    样例(数据间用空格隔开,两个0表示输入结束):         
                    1          1
                    1          2
                    1          3
                    2          1
                    3          1
                    3          2
                    0          0           
    表示M=3,N=3,编号为1的同学选择了项目1,2和3,编号为2的同学选择了项目1,编号为3的同学选了项目1和2


输出(以文件方式输出,文件名为iw,例如iw.out):
    第1行:编号为1的项目依次面试新同学的编号序列
    第2行:编号为2的项目依次面试新同学的编号序列
    ...
    第n行:编号为n的项目依次面试新同学的编号序列
    样例(数据间用空格隔开,0表示没有面试):
               1       3       2
               3       1       0
               0       0       1
    表示编号为1的项目在第一轮面试编号为1的同学,第二轮面试编号为3的同学,第三轮面试编号为2的同学
    编号为2的项目在第一轮面试编号为3的同学,第二轮面试编号为1的同学,第二轮不用面试
    编号为3的项目在第一轮和第二轮都不用面试,第三轮面试编号为1的同学。

 

 

代码

 

package com.ausky.work.pongo;

/**
 * 未来的某一年开始,很多创业团队开始在CSDN社区内办公,社区每年会组织同学与项目的双选会,即入职者与各个创业项目(团队)相互挑选,假设现在有M个项目,
 * 编号从1到M,另有N名同学,编号从1到N,每名同学能选择最多三个、最少一个感兴趣的项目。选定之后,HR会安排项目负责人和相应感兴趣的同学一对一面谈,
 * 每次面谈持续半小时。由于大家平时都很忙,所以咱们要尽量节约时间,请你按照以下的条件设计算法,帮助HR安排面试:
 * 
 * 1)同学很忙。项目负责人一次只能与一名同学面谈,而同学会在自己第一个面试开始时达到社区,最后一个面试结束后离开社区,
 * 如果参加一个项目组的面试后不能立即参加下一个项目组的面试,就必须在社区等待。所以请尽可能让同学的面试集中在某一时间段,减少同学在社区等待的时间。
 * 2)项目负责人很忙
 * 。众所周知,创业团队的负责人会有很多事情要做,所以他们希望能够将自己参与的面试集中在某一段时间内,请在保证1)的情况下,使得项目负责人等待的时间最少。
 * 3)HR很忙。从第一轮面试开始以后,所有HR都必须等到最后一轮面试结束,所以需要在保证1)和2)的同时,也能尽快解放掉所有的HR,
 * 即让第一轮面试到最后一轮面试之间持续的时间最短。
 * 
 * 
 * 
 * 输入(以文件方式输入,文件名为iw,例如iw.in): 第1行...第n行:同学的编号 项目的编号 样例(数据间用空格隔开,两个0表示输入结束): 1 1
 * 1 2 1 3 2 1 3 1 3 2 0 0
 * 表示M=3,N=3,编号为1的同学选择了项目1,2和3,编号为2的同学选择了项目1,编号为3的同学选了项目1和2
 * 
 * 
 * 输出(以文件方式输出,文件名为iw,例如iw.out): 第1行:编号为1的项目依次面试新同学的编号序列 第2行:编号为2的项目依次面试新同学的编号序列
 * ... 第n行:编号为n的项目依次面试新同学的编号序列 样例(数据间用空格隔开,0表示没有面试): 1 3 2 3 1 0 0 0 1
 * 表示编号为1的项目在第一轮面试编号为1的同学,第二轮面试编号为3的同学,第三轮面试编号为2的同学
 * 编号为2的项目在第一轮面试编号为3的同学,第二轮面试编号为1的同学,第二轮不用面试 编号为3的项目在第一轮和第二轮都不用面试,第三轮面试编号为1的同学。
 * 
 * @author xn-hyao-01
 * 
 */
public class Pongo_1021 {
	public static void main(String[] args) {
		Pongo_1021 pongo = new Pongo_1021();
		// 学生选择的项目
		int[][] studentChooses;
		studentChooses = new int[][] { { 1, 1 }, { 1, 2 }, { 1, 3 }, { 2, 1 },
				{ 2, 2 }, { 2, 3 }, { 3, 1 }, { 3, 2 }, { 3, 3 } };
		// 项目数量 及 学生数量
		int studentNum = 3;
		int companyNum = 0;

		for (int[] studentTmp : studentChooses) {
			studentNum = studentNum < studentTmp[0] ? studentTmp[0]
					: studentNum;
			companyNum = companyNum < studentTmp[1] ? studentTmp[1]
					: companyNum;
		}
		// 最后面试安排
		int[][] totalRes = new int[companyNum][studentNum];

		for (int i = 0; i < studentChooses.length; i++) {
			int studentId = studentChooses[i][0];
			int companyId = studentChooses[i][1] - 1;
			for (int tmpSize = 0; tmpSize < studentNum; tmpSize++) {
				if (totalRes[companyId][tmpSize] == 0) {
					totalRes[companyId][tmpSize] = studentId;
					break;
				}
			}
		}

		for (int line = 0; line < companyNum; line++) {
			int[] studentSeat = totalRes[line];
			for (int tmpSeat = 0; tmpSeat < studentSeat.length; tmpSeat++) {
				for (int littleLine = 0; littleLine < line; littleLine++) {
					if (studentSeat[tmpSeat] != 0
							&& totalRes[littleLine][tmpSeat] == studentSeat[tmpSeat]) {
						studentSeat = pongo.changeSeat(studentSeat, tmpSeat);
						tmpSeat--;
						break;
					}
				}
			}
			totalRes[line] = studentSeat;
		}

		for (int[] tmps : totalRes) {
			for (int i : tmps) {
				System.out.print(i + " ");
			}
			System.out.println("");
		}

	}

	public int[] changeSeat(int[] target, int start) {
		int size = target.length;
		int middleTmp = 0;
		for (int position = start; position <= size + start; position++) {
			int val = target[position % size];
			target[position % size] = middleTmp;
			middleTmp = val;
		}
		return target;
	}
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值