排座椅(贪心+排序)

解题思路:

想让更少的人交头接耳,就必须保证一条过道可以尽可能多的分隔开两个说话的人,所以定义一个结构体,里面包含两个成员,一个是记录某两排或者某两列之间说话的人数,一个是记录分隔开的座位号。然后进行排序,先按照人数从大到小排序,人数越多说明这条过道能把更多说话的人分开。再按照座位序号降序。

代码:

#include <bits/stdc++.h>
using namespace std;
struct fun{
    int num;//分隔的人数
    int idex;//分隔的座椅号
}h[2010],s[2010];
int cmp(fun a,fun b)
{
    if(a.num!=b.num)
        return a.num>b.num;
}
int cmp1(fun a,fun b)
{
    if(a.idex!=b.idex)
        return a.idex<b.idex;
}
int main()
{
  int m,n,k,l,d;
  cin>>m>>n>>k>>l>>d;
  int x,y,p,q;
  int ans1=0,ans2=0;
  for(int i=1;i<=d;i++)
  {
    cin>>x>>y>>p>>q;
    if(x==p)
    {
        s[min(y,q)].num++;
        s[min(y,q)].idex=min(y,q);
    }
    else if(y==q)
    {
       h[min(x,p)].num++;
       h[min(x,p)].idex=min(x,p);
    }
  }
  sort(h+1,h+m+1,cmp);
  sort(h+1,h+k+1,cmp1);
  sort(s+1,s+n+1,cmp);
  sort(s+1,s+l+1,cmp1);
  for(int i=1;i<=k;i++)
  {
      if(i!=k)
        cout<<h[i].idex<<" ";
      else
        cout<<h[i].idex;
  }
  cout<<endl;
  for(int i=1;i<=l;i++)
  {
      if(i!=l)
        cout<<s[i].idex<<" ";
      else
        cout<<s[i].idex;
  }
  return 0;
}

### P1056 座椅算法 C++ 实现 以下是基于问题描述以及参考资料中的核心思想设计的一个完整的 C++ 解决方案。该程序通过统计可能的切割位置并选取最优解来满足题目需求。 #### 代码实现 ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; struct State { int pos; // 切割位置(行号或列号) int count; // 对应位置上的交头接耳学生对数 }; bool cmp(const State &a, const State &b) { if (a.count != b.count) return a.count > b.count; return a.pos < b.pos; } int main() { int m, n, k, l, d; cin >> m >> n >> k >> l >> d; vector<int> x(m + 1, 0); // 行方向切割计数器 vector<int> y(n + 1, 0); // 列方向切割计数器 for (int i = 0; i < d; ++i) { int aa, ab, ba, bb; cin >> aa >> ab >> ba >> bb; if (aa == ba) { // 竖直切割 y[min(ab, bb)]++; } else { // 水平切割 x[min(aa, ba)]++; } } // 处理水平切割 vector<State> rows; for (int i = 1; i <= m; ++i) { if (x[i] > 0) { rows.push_back(State{i, x[i]}); } } sort(rows.begin(), rows.end(), cmp); vector<int> selected_rows; for (int i = 0; i < min((int)rows.size(), k); ++i) { selected_rows.push_back(rows[i].pos); } sort(selected_rows.begin(), selected_rows.end()); // 输出选中的行 for (size_t i = 0; i < selected_rows.size(); ++i) { cout << selected_rows[i]; if (i != selected_rows.size() - 1) cout << " "; } cout << endl; // 处理垂直切割 vector<State> cols; for (int j = 1; j <= n; ++j) { if (y[j] > 0) { cols.push_back(State{j, y[j]}); } } sort(cols.begin(), cols.end(), cmp); vector<int> selected_cols; for (int i = 0; i < min((int)cols.size(), l); ++i) { selected_cols.push_back(cols[i].pos); } sort(selected_cols.begin(), selected_cols.end()); // 输出选中的列 for (size_t i = 0; i < selected_cols.size(); ++i) { cout << selected_cols[i]; if (i != selected_cols.size() - 1) cout << " "; } cout << endl; return 0; } ``` #### 关键点解析 1. **数据结构的选择** 使用 `vector` 存储每一行和每一列的切割次数,便于动态扩展和访问[^1]。 2. **贪心策略的应用** 题目要求选择最多交头接耳学生的切割位置,因此采用贪心方法逐一挑选最大值,并将其标记为已处理状态。为了优化时间复杂度,引入自定义排序函数 `cmp` 来加速寻找最佳切割位置的过程[^2]。 3. **输入输出细节** 根据题目说明,最终需按升序列输出选定的切割位置,这一步骤在代码中通过两次调用 `sort()` 函数完成[^3]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小阿丁呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值