【NOIP】排座椅
排座椅
https://ac.nowcoder.com/acm/problem/16618
此题是一道十分考察细节的一道题。
此题就是让我们求的矩阵里,分割出
条横线和
条竖线,要求两两相邻的点,尽可能多的不再相邻。
题目已经告诉你了,这是一道贪心!!!
为什么是贪心呢???
要使答案最优,肯定要让条横线和
条竖线要穿过尽可能多的会讲话的两个人!
如图:
如果只有一条横线和竖线上图中的最优解,很明显是这样:
所以我们的贪心是成立的
我们需要用结构体维护能穿过的讲话同桌个数和从第几行(列)分割的!
然后按照能穿过的同桌个数由大到小排序,最后输出答案。
code:
统计当前行列能穿过的同桌个数 if(x==x2){ int yy=min(y,y2); cy[yy].x++; cy[yy].id=yy 从yy开始分割的 } else if(y==y2){ int xx=min(x,x2); 求最小可以防便后面输出处理 cx[xx].x++; cx[xx].id=xx; 从xx开始分割的 } 由大到小排序。 sort(cx+1,cx+1+m,cmp); sort(cy+1,cy+1+n,cmp); 输出答案。
然后你照着码了一下代码会发现。。。 WA10分
WA10分,那我怎么可能服气,于是我手构了一组十分坑人的数据:
4 6 2 1 3 1 1 2 1 3 1 4 1 3 4 4 4
程序输出:
3 1 0
我手算了一下,发现答案没问题,我万思不得其解,然后看了看题目。。。。。
心中一万只羊驼在奔腾!!!
咳咳,回到正题
既然要保证 &&
那么,我们就可以将
排序,即可AC!
code:
#include<bits/stdc++.h> using namespace std; int m,n,a,b,d; struct node{int x,id;}; node cx[1005],cy[1005]; 对能穿过同桌个数进行由大到小排序 bool cmp(node a,node b){return a.x>b.x;} 对所有最优解进行id的有小到大排序 bool cmp_id(node a,node b){return a.id<b.id;}; int main(){ scanf("%d %d %d %d %d",&m,&n,&a,&b,&d); a表示a条横线,b表示b条竖线 for(int i=1;i<=d;i++){ int x,y,x2,y2; scanf("%d %d %d %d",&x,&y,&x2,&y2); 统计当前行列能穿过的同桌个数 if(x==x2){ int yy=min(y,y2); cy[yy].x++; 统计个数 cy[yy].id=yy; 标记所在列 } else if(y==y2){ int xx=min(x,x2); cx[xx].x++; cx[xx].id=xx; 标记所在行 } } 找出最优解 sort(cx+1,cx+1+m,cmp); sort(cy+1,cy+1+n,cmp); 对最优解排序 sort(cx+1,cx+1+a,cmp_id); sort(cy+1,cy+1+b,cmp_id); for(int i=1;i<a;i++) printf("%d ",cx[i].id); printf("%d\n",cx[a].id); for(int i=1;i<b;i++) printf("%d ",cy[i].id); printf("%d\n",cy[b].id); return 0;完美结束 }