【贪心】排座椅

描述 Description
   上课的时候总有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上课时会交头接耳。同学们在教室中坐成了M行N列,坐在第i行第j列的同学的位置是(i,j),为了方便同学们进出,在教室中设置了K条横向的通道,L条纵向的通道。于是,聪明的小雪想到了一个办法,或许可以减少上课时学生交头接耳的问题:她打算重新摆放桌椅,改变同学们桌椅间通道的位置,因为如果一条通道隔开了两个会交头接耳的同学,那么他们就不会交头接耳了。 
   请你帮忙给小雪编写一个程序,给出最好的通道划分方案。在该方案下,上课时交头接耳的学生对数最少。 
输入格式 Input Format
输入的第一行,有5各用空格隔开的整数,分别是M,N,K,L,D(2<=N,M<=1000,0<=K<M,0<=L<N,D<=2000)。 
接下来D行,每行有4个用空格隔开的整数,第i行的4个整数Xi,Yi,Pi,Qi,表示坐在位置(Xi,Yi)与(Pi,Qi)的两个同学会交头接耳(输入保证他们前后相邻或者左右相邻)。 
输入数据保证最优方案的唯一性。 
输出格式 Output Format
第一行包含K个整数,a1a2……aK,表示第a1行和a1+1行之间、第a2行和第a2+1行之间、…、第aK行和第aK+1行之间要开辟通道,其中ai< ai+1,每两个整数之间用空格隔开(行尾没有空格)。 
第二行包含L个整数,b1b2……bk,表示第b1列和b1+1列之间、第b2列和第b2+1列之间、…、第bL列和第bL+1列之间要开辟通道,其中bi< bi+1,每两个整数之间用空格隔开(行尾没有空格)。 
样例输入 Sample Input [ 复制数据]
样例输出 Sample Output [ 复制数据]


写了一堆复杂的东西。
因为没看到要按字典序输出,让我在普及组题上挂了一次、

 #include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
using std::sort;

struct Heap
{
	long tree[4010];
	long size;
	const long* data;
	Heap(const long* a){data=a;size=0;}
	void swap(long a,long b)
	{
		long tmp = tree[a];
		tree[a] = tree[b];
		tree[b] = tmp;
	}
	void adjust_up(long l)
	{
		while (l>1)
		{
			if (data[tree[l>>1]]<data[tree[l]])swap(l>>1,l);
			else break;
			l >>= 1;
		}
	}
	void adjust_down(long l)
	{
		while ((l<<=1)<size+1)
		{
			if (l+1<size+1&&data[tree[l+1]]>data[tree[l]]) l++;
			if (data[tree[l>>1]]<data[tree[l]])swap(l>>1,l);
			else break;
		}
	}
	void push(long i)
	{
		size++;
		tree[size]=i;
		adjust_up(size);
	}
	void pop()
	{
		if (size > 0)
		{
			tree[1] = tree[size--];
			adjust_down(1);
		}
	}
	long top()
	{
		return tree[1];
	}
};

long a[1050];
long b[1050];
Heap h1(a);
Heap h2(b);
long tmp[1050];

long getint()
{
	long rs=0;bool sgn=1;char tmp;
	do tmp = getchar();
	while (!isdigit(tmp)&&tmp-'-');
	if (tmp == '-'){tmp=getchar();sgn=0;}
	do rs=(rs<<3)+(rs<<1)+tmp-'0';
	while (isdigit(tmp=getchar()));
	return sgn?rs:-rs;	
}

int main()
{
	long n = getint();
	long m = getint();
	long k = getint();
	long l = getint();
	long d = getint();

	for (long i=1;i<d+1;i++)
	{
		long x1 = getint();
		long y1 = getint();
		long x2 = getint();
		long y2 = getint();

		if (x1 == x2)
		{
			if (y1 > y2)
				b[y2] ++;
			else
				b[y1] ++;
		}
		else
		{
			if (x1 > x2)
				a[x2] ++;
			else
				a[x1] ++;
		}
	}

	for (long i=1;i<n+1;i++)
	{
		h1.push(i);
	}
	
	for (long i=1;i<m+1;i++)
	{
		h2.push(i);
	}

	tmp[0] = 0;
	for (long i=1;i<k+1;i++)
	{
		tmp[++tmp[0]] = h1.top();
		h1.pop();
	}
	sort(tmp+1,tmp+1+tmp[0]);
	for (long i=1;i<k+1;i++)
	{
		printf("%ld ",tmp[i]);
	}
	tmp[0] = 0;
	for (long i=1;i<l+1;i++)
	{
		tmp[++tmp[0]] = h2.top();
		h2.pop();
	}
	sort(tmp+1,tmp+1+tmp[0]);
	printf("\n");
	for (long i=1;i<l+1;i++)
	{
		printf("%ld ",tmp[i]);
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值