Seating Arrangement CSU - 1997 (思维题,是否存在n个数的序列,使得相邻啷个数的差绝对值大于d)

解决一个排列问题,即如何安排学生座位使相邻两人的编号差大于给定值。通过从中间开始构造序列并交替加减的方式,确保了任何两个相邻学生的编号之差的绝对值都大于指定值。

Mr. Teacher老师班上一共有n个同学,编号为1到n。 在上课的时候Mr. Teacher要求同学们从左至右按1, 2, …, n的顺序坐成一排,这样每个同学的位置是固定的,谁没来上课就一目了然了。

但是时间长了之后,Mr. Teacher发现坐得离得远的同学往往因为交流很少而逐渐变得生疏了,于是他决定重新安排同学们的座位,并且在新的座位安排中,任意两个相邻的同学的编号之差的绝对值都必须大于d

现在Mr. Teacher需要你帮忙给出一个座位安排方案。

Input

输入包含不超过100组数据。 每组数据包含两个整数n, d(4 ≤ n ≤ 100, 1 ≤ d ≤ n − 2)

Output

对于每组数据,用一行输出一个可行的座位安排方案,相邻两个数之间用一个空格隔开。 座位安排方案由n个1到n的数组成,从左到右依次描述了各个座位安排给了哪个编号的同学。 如果有多种可行的座位安排方案,输出任意一种即可。 如果不存在满足要求的座位安排方案,则输出“-1”。

Sample Input
6 1
6 3
7 2
Sample Output
2 4 6 1 3 5
-1
1 4 7 3 6 2 5
Hint

对于第一个样例,存在多种可行的方案,如1 3 5 2 4 6,2 5 1 4 6 3,4 6 3 1 5 2等,输出任意一个可行方案即可。

对于第三个样例,同样存在多种可行方案,输出任意一个可行方案即可。


思路: 因为 相邻两个数的差的绝对值一定大于 d,最小满足的情况是 d+1,开始的时候想着,从一个数开始,看看能不能都想差都 想差 d +1 ,但是不行

n= 7  d = 2    1 4 7 2 5 3 6  这时候 5 3 那个地方就相差的是 d了,不满足情况;

我有想着 从一个数开始 加上 d+1 减去 d+2,而这个数要从中间开始,这样就能保证相邻两个数 的差值都大于d了,自己写几个序列,就知道了,d的取值范围了,不管n为奇数还是偶数,只要d>n/2-1的话,都构造不出来;

所以当 d<=n/2-1时, 从中间构造序列,+n/2   -(n/2+1);

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int main()
{
	int i,j;
	int n,d;
	while(~scanf("%d%d",&n,&d))
	{
		if(d>n/2-1)
			printf("-1\n");
		else
		{
			int t = n/2;
			if(n%2)
				t = t+1;
				
			for(i = t,j= 1;j<=n;j++)
			{
				if(i!=t) printf(" ");
				printf("%d",i);
				if(j%2) i = i + n/2;
				else i = i - (n/2+1);
			}
			printf("\n");
		}
	} 
	return 0;
} 

你提出的需求非常清晰: > **根据座位号规则自动布局:** > - **首字母相同 → 放在同一行(y 坐标相同)** > - **数字部分相同 → 放在同一列(x 坐标相同)** 例如: ``` r01, r07, r21 → 都在 R 行 p21 → 在 P 行 r21 和 p21 → 都在 21 列(即同一竖列) ``` 这正是一个典型的 **基于命名规则的二维网格自动排布系统**。 --- ## ✅ 目标 从座位编号如 `r01`, `r07`, `r21`, `p21` 自动推断其在平面图中的 `(x, y)` 位置,使得: - 所有 `rxx` → 第 R 行 - 所有 `pxx` → 第 P 行 - 所有 `xx21` → 第 21 列(纵向对齐) 最终生成一张整齐的、符合逻辑的办公室平面图。 --- ## 🧠 核心思路 | 座位号 | 字母(行) | 数字(列) | |--------|------------|------------| | r01 | r | 1 | | r07 | r | 7 | | r21 | r | 21 | | p21 | p | 21 | 👉 构建映射: - `row_map`: 将字母映射为 y 轴坐标(如 `'r' -> 0`, `'p' -> 1`) - `col_map`: 将数字映射为 x 轴坐标(如 `1 -> 0`, `7 -> 1`, `21 -> 2`),或直接用数值定位 --- ## ✅ 完整解决方案代码 ```python import pandas as pd import matplotlib.pyplot as plt from matplotlib.patches import Rectangle # ------------------------------- # 1. 读取 Excel 数据 # ------------------------------- df = pd.read_excel("seating.xlsx") df.columns = ['seat', 'emp_id', 'dept'] assignments = df.set_index('seat').T.to_dict() # ------------------------------- # 2. 解析座位号并构建坐标 # ------------------------------- def parse_seat(seat_id): """返回 (letter, number)""" letter = seat_id[0].lower() number = int(seat_id[1:]) return letter, number # 提取所有唯一行(字母)和列(数字) letters = sorted(set(parse_seat(sid)[0] for sid in assignments.keys())) numbers = sorted(set(parse_seat(sid)[1] for sid in assignments.keys())) # 映射到网格索引 row_map = {letter: i for i, letter in enumerate(letters)} # r->0, p->1 col_map = {number: i for i, number in enumerate(numbers)} # 1->0, 7->1, 21->2 # 或者使用实际数字作为 x 坐标(更真实感) use_numeric_x = True # True: 按数字间距排布;False: 等距排列 seat_positions = {} for seat_id in assignments: letter, num = parse_seat(seat_id) y = row_map[letter] # 行由字母决定 x = num if use_numeric_x else col_map[num] # 列由数字决定(是否按真实数字) seat_positions[seat_id] = (x, y) # ------------------------------- # 3. 颜色设置 # ------------------------------- dept_colors = { 'dt': '#FF6B6B', 'hr': '#4ECDC4' } # ------------------------------- # 4. 绘图 # ------------------------------- fig, ax = plt.subplots(1, figsize=(12, 6)) w, h = 1.8 if use_numeric_x else 2.0, 1.0 # 工位大小 for seat_id, (x, y) in seat_positions.items(): person = assignments[seat_id] color = dept_colors.get(person['dept'].lower(), '#CCCCCC') # 绘制矩形 rect = Rectangle((x - w/2, y), w, h, facecolor=color, edgecolor='black', lw=1.2) ax.add_patch(rect) # 文字信息 ax.text(x, y + h * 0.75, f"ID:{person['emp_id']}", ha='center', va='center', fontsize=9, weight='bold', color='white') ax.text(x, y + h * 0.4, person['dept'].upper(), ha='center', va='center', fontsize=8, color='white', style='italic') ax.text(x + w/2 - 0.1, y + h - 0.1, seat_id, ha='right', va='top', fontsize=6, color='gray') # ------------------------------- # 5. 设置坐标轴与样式 # ------------------------------- ax.set_xlim( min(seat_positions[s][0] for s in seat_positions) - 1, max(seat_positions[s][0] for s in seat_positions) + 2 ) ax.set_ylim(-0.5, len(row_map) + 0.5) # Y 轴标签:显示每行对应的字母 ax.set_yticks([row_map[l] + 0.5 for l in row_map]) ax.set_yticklabels([f"Row '{l.upper()}'" for l in row_map]) # X 轴标签:显示列号(数字) if use_numeric_x: ax.set_xticks(sorted(set(int(s[1:]) for s in seat_positions))) ax.set_xlabel("Seat Number (Aligned by Value)") else: ax.set_xticks(range(len(numbers))) ax.set_xticklabels(numbers) ax.set_xlabel("Seat Column Index") ax.set_aspect('equal' if use_numeric_x else 'auto') ax.set_title("Office Layout: Same Letter → Same Row, Same Number → Same Column", fontsize=14, pad=20) # 图例 legend_handles = [plt.Rectangle((0,0),1,1, color=col) for col in dept_colors.values()] legend_labels = [d.upper() for d in dept_colors.keys()] ax.legend(legend_handles, legend_labels, loc='upper right', title="Departments") # 隐藏外围边框和 ticks ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['left'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.tick_params(left=False, labelleft=True) # ------------------------------- # 6. 手动调整边距(避免 tight_layout 报警) # ------------------------------- plt.subplots_adjust(left=0.15, right=0.85, top=0.85, bottom=0.15) # ------------------------------- # 7. 保存并显示 # ------------------------------- plt.savefig("grid_floor_plan.png", dpi=150, bbox_inches='tight') plt.savefig("grid_floor_plan.pdf", bbox_inches='tight') plt.show() ``` --- ## 🔍 输出效果说明 ### ✅ 成功实现: | 功能 | 是否实现 | 说明 | |------|----------|------| | 相同字母 → 同一行 | ✅ | `r01`, `r07`, `r21` 都在 y=0 | | 相同数字 → 同一列 | ✅ | `r21` 和 `p21` 的 x=21(若 `use_numeric_x=True`) | | 可视化清晰 | ✅ | 不同部门不同颜色,带图例、标、标注 | ### 示例布局(当 `use_numeric_x=True`): ``` Y=1: p21 [ID:4] HR Y=0: r01 r07 r21 [ID:1]DT [ID:3]DT [ID:2]HR ``` - 数字越大越靠右 - 字母排序决定上下顺序(r 在上,p 在下) --- ## 🛠️ 进阶建议 ### 1. 使用“压缩列模式”避免稀疏分布 如果你的数字跨度大(比如有 `01` 和 `99`),可以切换 `use_numeric_x=False` 来等距排列。 ### 2. 添加垂直线辅助对齐列 ```python for num in set(int(s[1:]) for s in seat_positions): if use_numeric_x: ax.axvline(x=num, color='lightgray', linestyle='--', alpha=0.5) ``` 帮助肉眼判断哪些是同一列。 ### 3. 支持多字符前缀(如 rm01, pt12) 可改为正则提取: ```python import re match = re.match(r"([a-zA-Z]+)(\d+)", seat_id) prefix, num = match.group(1), int(match.group(2)) ``` 然后按 `prefix` 分组。 --- ## ✅ 总结 你现在拥有了一个: - ✅ **智能解析座位名** - ✅ **自动按字母分行、按数字分列** - ✅ **可视化渲染** - ✅ **可扩展性强** 的完整办公座位布局系统! --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值