题的链接:P1056 排座椅
题解: 题目说输出最好的方案,说明方案不止一种,要输出每条切割线切得人最多的线,所以就是典型的贪心,先统计要切割线路的次数,再输出前K或L个元素(输出按照行列号从小到大输出)就行。
首先说明一个问题:给出的K和L是切割线的一部分,也就是所有切割线按从大到小排完序的行前K,列前L个;这样还不行,输出必须输出所切割行下标或列下标要从小到大输出,所以还得对要输出的前K或L个元素按照下标从小到大再排一次序,才能输出。
知识点:关于cmp函数参数中的&符号!
参考代码1.0: 结构体存储,自定义cmp调用sort排序
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
#define MAX 20010
using namespace std;
int M, N, K , L, D;
int x1, y1, x2, y2;
struct Node
{
int w;
int v;
};
Node x[2010], y[2010];
bool cmp1(const Node &a, const Node &b)
{
return a.w > b.w;
}
bool cmp2(const Node &a, const Node &b)
{
return a.v < b.v;
}
int main()
{
cin >> M >> N >> K >> L >> D;
for(int i = 1; i <= M; i++) x[i].v = i;
for(int i = 1; i <= N; i++) y[i].v = i;
while(D--)
{
cin >> x1 >> y1 >> x2 >> y2;
if(x1 == x2)
{
int t = min(y1, y2);
y[t].w++;
}
if(y1 == y2)
{
int t = min(x1, x2);
x[t].w++;
}
}
sort(x, x + M, cmp1);
sort(y, y + N, cmp1);
sort(x, x + K, cmp2);
sort(y, y + L, cmp2);
for(int i = 0; i < K; i++) cout << x[i].v <<" ";
cout << endl;
for(int i = 0; i < L; i++) cout << y[i].v <<" ";
cout << endl;
return 0;
}
参考代码2.0: 结构体存储,四次冒泡排序。切割次数从大到小,下标从小到大。
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
#define MAX 20010
using namespace std;
int M, N, K , L, D, pos;
int x1, y1, x2, y2;
struct Node
{
int w, v;
};
Node x[2010], y[2010];
int main()
{
cin >> M >> N >> K >> L >> D;
while(D--)
{
cin >> x1 >> y1 >> x2 >> y2;
if(x1 == x2)
{
int t = min(y1, y2);
y[t].w++;
y[t].v = t;
}
if(y1 == y2)
{
int t = min(x1, x2);
x[t].w++;
x[t].v = t;
}
}
for(int i = 0; i < M; i++)
for(int j = M - 1; j >= i + 1; j--)
if(x[j].w > x[j - 1].w) swap(x[j], x[j - 1]);
for(int i = 0; i < N; i++)
for(int j = N - 1; j >= i + 1; j--)
if(y[j].w > y[j - 1].w) swap(y[j], y[j - 1]);
for(int i = 0; i < K; i++)
for(int j = K - 1; j >= i + 1; j--)
if(x[j].v < x[j - 1].v) swap(x[j], x[j - 1]);
for(int i = 0; i < L; i++)
for(int j = L - 1; j >= i + 1; j--)
if(y[j].v < y[j - 1].v) swap(y[j], y[j - 1]);
for(int i = 0; i < K; i++) cout << x[i].v << " ";
cout << endl;
for(int i = 0; i < L; i++) cout << y[i].v << " ";
cout << endl;
return 0;
}
参考代码3.0: 没有用到排序和cmp,用数组存储切割下标的次数,再查找K次或L次最大切割数标记出来,将其存入新数组,for循环从小到大输出,(新数组除了K,L个数据,其他都是0元素)
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
#define MAX 20010
using namespace std;
int M, N, K , L, D, pos;
int x1, y1, x2, y2;
int x[2010], y[2010];
int xx[2010], yy[2010];
int main()
{
cin >> M >> N >> K >> L >> D;
while(D--)
{
cin >> x1 >> y1 >> x2 >> y2;
if(x1 == x2)
{
int t = min(y1, y2);
y[t]++;
}
if(y1 == y2)
{
int t = min(x1, x2);
x[t]++;
}
}
for(int i = 0; i < K; i++)
{
int maxx = 0;
for(int j = 1; j < M; j++)
{
if(maxx < x[j]) maxx = x[j], pos = j;
}
x[pos] = 0; xx[pos] = 1;
}
for(int i = 0; i < L; i++)
{
int maxx = 0;
for(int j = 1; j < N; j++)
{
if(maxx < y[j]) maxx = y[j], pos = j;
}
y[pos] = 0; yy[pos] = 1;
}
for(int i = 0; i < M; i++) if(xx[i]) cout << i <<" ";
cout << endl;
for(int i = 0; i < N; i++) if(yy[i]) cout << i <<" ";
cout << endl;
return 0;
}