P3566 [POI2014] KLO-Bricks 题解
大致意思:
现在有 nnn 种颜色的砖块,第一个必须放第 ppp 种颜色,最后一定得放第 qqq 种颜色,剩余中间的需要自己构造,使得每相邻两个砖块的颜色不相等,有解随便输出任意一种,无解则输出 000。
大致思路:
这是一道很好的贪心构造题,最优的方案,肯定就是先放最少最多,用最多的来分隔少的,因为这样最多的可以放置的更为均匀,以达到我们实现最优方案的目的,不然会导致多的前面放的过少,后面聚在一堆,实现出来的代码显示的是无解。当然如果当前最多的颜色与前面一项相等,那么我们要取一二大的,以此类推。
而我们知道了,想要实现此方法需要一边运行放颜色,一边排序,如果直接用用排序函数,占用时间太大,肯定会超时,那么我们就可以用到优先队列,它是可以边运行边排序的。
我们可以用变量 sss,记录总砖块数,接着通过循环实现放砖块:
-
当前最多的砖块他的下标与前面相等,那么我可以用 ttt 记录最多砖块的数量,把它从队列中移除,找到第二多的砖块,将这个砖块的数量减 111。
-
当前最多的砖块他的下标与前面不相等,直接用此砖块,将这个砖块的数量减 111。
当然,在过程中我们还要判断,本种砖块数是否大于 000,和此时队列里还有没有砖块,如果没有砖块,则无解。
代码实现:
#include<bits/stdc++.h>
using namespace std;
int n,p,y,s;
int ar[1000005];
bool f;
struct node{
int x;
int id;
}a[1000005];
bool operator <(node l,node r){
if (l.x != r.x) return l.x<r.x;
if (l.id == y) return 0;
if (r.id == y) return 1;
return 0;
}
priority_queue<node> q;
int main(){
cin>>n>>p>>y;
for(int i=1;i<=n;i++){
cin>>a[i].x;
if(i==p) a[i].x--;
if(i==y) a[i].x--;
s+=a[i].x;
a[i].id=i;
q.push(node{a[i].x,i});
}
int u=p;
ar[s+2]=y;
for(int i=2;i<=s+1;i++){
node t=q.top();q.pop();
if(t.x>0) t=t;
else{
f=1;
break;
}
if(t.id!=u&&t.x>0){
ar[i]=t.id;
q.push(node{t.x-1,t.id});
u=ar[i];
}else if(q.size()&&t.x>0){
node v=q.top();
q.pop();
ar[i]=v.id;
q.push(node{v.x-1,v.id});
q.push(node{t.x,t.id});
u=ar[i];
}else if(!q.size()){
f=1;
break;//不加 RE,我找了两位大佬才调出来
}
}
if(f){
cout<<"0";
return 0;
}
for(int i=1;i<=s+1;i++){
if(ar[i]==ar[i+1]){
f=1;
}
}
if(f){
cout<<"0";
return 0;
}
cout<<p<<" ";
for(int i=2;i<=s+1;i++){
cout<<ar[i]<<" ";
}
cout<<ar[s+2];
return 0;
}
这样这道题就结束啦!
文章讲述了如何使用贪心策略和优先队列解决一道关于颜色砖块排列的问题,保证每相邻两块颜色不相同。通过先放最少和最多的砖块,利用优先队列实时更新,找出最优解或判断无解。
384

被折叠的 条评论
为什么被折叠?



