【贪心】排座椅(seat)

http://icpc.upc.edu.cn/problem.php?cid=1674&pid=0

  昨天喝完了第一杯水,就贪心地吃吃干粮吧!这道题初看脑子里只有四个字:动态规划!!!(才没有想要暴力搜索呢)之后细细思考了一遍,其实可以保存拦截每一行每一列能阻止的同学数量,然后按拦截数量排一个序~(因为拦截行不影响拦截列,所以不用DP)这里还没完!因为还要按顺序输出,所以还要解决序号的问题,我们可以发现,完全可以用结构体分别保存编号和数量,再按照编号排一次序,就可以很简单地解决这个问题了~QAQ代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
struct str
{
    int num,sum;
};
bool cmp1(str a,str b)
{
    return a.sum > b.sum;
}
bool cmp2(str a,str b)
{
    return a.num < b.num;
}
str r[2001],c[2001];
int i,n,m,l,k,d,a,b,x,y;
int main()
{
    scanf("%d%d%d%d%d",&m,&n,&k,&l,&d);
    for(i=0; i<m; i++)
        r[i].num=i+1;
    for(i = 0; i <n; i++)
        c[i].num = i+1;
    for(i =1; i <=d; i++)
    {
        scanf("%d%d%d%d",&a,&b,&x,&y);
        if(a == x)
            c[min(b,y) - 1].sum++;;
        if(b == y)
            r[min(a,x) - 1].sum++;
    }
    sort(r,r+m,cmp1);
    sort(c,c+n,cmp1);
    sort(r,r+k,cmp2);
    sort(c,c+l,cmp2);
    for(i =0; i<k; i++)
        if(i!=k-1)
            printf("%d ",r[i].num);
        else
            printf("%d\n",r[i].num);
    for(i = 0; i < l; i++)
        if(i!=l-1)
            printf("%d ",c[i].num);
        else
            printf("%d\n",c[i].num);
}

 

### 解题思路分析 PTA上的座椅问题通常涉及列组合、贪心算法或动态规划等思想。以下是对该问题的详细分析: #### 1. 问题描述 座椅问题通常要求根据特定规则安学生座位,使得某种目标达到最优。例如,可能需要最小化学生的不满情绪、最大化相邻学生之间的相似性,或者满足某些约束条件。具体规则需要根据题目描述进行调整[^1]。 #### 2. 核心解题方法 此类问题通常可以通过以下几种方法解决: - **贪心算法**:如果问题的目标是最小化某种代价,可以尝试使用贪心策略,逐步选择当前最优解,最终得到全局最优解。 - **动态规划**:当问题具有重叠子问题和最优子结构性质时,可以考虑使用动态规划。通过定义状态转移方程,逐步计算出最优解。 - **分治法**:对于复杂的问题,可以将其分解为若干子问题,分别求解后再合并结果。 - **数学建模**:有时问题可以通过数学公式或模型进行抽象,转化为已知的经典问题(如线性规划、图论问题等)。 #### 3. 具体实现步骤 以下是解决座椅问题的一个通用框架: ```python # 示例代码:基于贪心算法的座椅问题 def arrange_seats(students, constraints): # 按照某种规则对学生进行序 students.sort(key=lambda x: x['priority'], reverse=True) # 假设优先级越高越靠前 # 初始化座位安 seats = [] for student in students: # 尝试将学生安到合适的位置 placed = False for i in range(len(seats)): if satisfies_constraints(student, seats[i], constraints): # 检查是否满足约束条件 seats.insert(i, student) placed = True break if not placed: seats.append(student) # 如果无法插入,则放在最后 return seats def satisfies_constraints(student1, student2, constraints): # 检查两个学生是否满足约束条件 for constraint in constraints: if not constraint(student1, student2): return False return True ``` #### 4. 注意事项 - 确保输入数据的正确性和完整性。 - 在实现过程中,注意边界条件的处理,例如空座位、单个学生等情况。 - 对于复杂问题,可以尝试多种算法,并比较其性能和结果。 #### 5. 时间与空间复杂度分析 - 贪心算法的时间复杂度通常较低,为 \(O(n \log n)\),主要取决于序操作。 - 动态规划的时间复杂度较高,通常为 \(O(n^2)\) 或更高,但可以保证全局最优解。 - 分治法的时间复杂度取决于子问题的划分方式,通常为 \(O(n \log n)\)。 ### 示例应用 假设需要安 \(n\) 名学生坐在一椅子上,且希望相邻学生的身高差尽可能小。可以按照以下方法实现: ```python def min_height_difference(arrangement): total_diff = 0 for i in range(1, len(arrangement)): total_diff += abs(arrangement[i]['height'] - arrangement[i-1]['height']) return total_diff students = [{'name': 'A', 'height': 160}, {'name': 'B', 'height': 170}, {'name': 'C', 'height': 150}] constraints = [] # 假设没有额外约束 optimal_arrangement = arrange_seats(students, constraints) print("Optimal Arrangement:", optimal_arrangement) print("Minimum Height Difference:", min_height_difference(optimal_arrangement)) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值