优先队列嘛,大家都知道队列吧。对 就是那个queue同志。从头和尾都可以取,但是但是呢。如果你要取特定的的值呢。例如你要取一个队列中最大的或最小的那个呢。这时候队列就不是很适用了。即使能用复杂度也到n^2了(就是遍历)而且也麻烦。而优先队列(priority-queue)哎,顾名思义就是在queue前面加了个优先,哈哈。大概就是在结构体里面加个bool operator<(node a,node b){ return a.s<b.s}就是最顶上一个换成最小的依次向下。换成大于号就依次向下。不过今天做了个题目,大概就是给你三杯子,最后一个杯子里是充满水的,而前俩个是空的,如何每次倒水的操作只能是将该杯子倒满或者把自己全部倒掉。如何让你量取出d升水。每个杯子均无刻度,如果取不到就取最接近的,就是改变一个状态
#include"iostream"#include"string"
#include"cstring"
#include"algorithm"
#include"cmath"
#include"map"
#include"queue"
#include"vector"
#include"cstdio"
#include"cstdlib"
#include"set"
#include"sstream"
#include"stack"
typedef long long ll ;
using namespace std;
int vis[205][205],ans[205],st[3]; //可以将当前概念化为一个二维数组
struct node {
int str[3],s; //str[3]代表当前状态 ,s表示当前状态倒的水
bool operator < (const node &rhs) const{ //这个其实就是重载符,相当于俩个比较了
return s>rhs.s; //优先队列,优先输出大的
}
};
void update(const node &u){
for(int i=0;i<3;i++){
int p=u.str[i]; //得到当前水需要的水量
if(ans[p]<0||u.s<ans[p]) ans[p]=u.s; // 更新答案
}
}
void solve(int a,int b,int c,int d){
st[0]=a,st[1]=b,st[2]=c; //记录初始状态
fill(vis,0); //类似地图,避免重复
fill(ans,-1);
priority_queue<node>Q;
node sta;
sta.s=0;
sta.str[0]=0,sta.str[1]=0,sta.str[2]=c;
Q.push(sta);
vis[0][0]=1;
while(!Q.empty()){
node u=Q.top(); Q.pop();
update(u);
if(ans[d]>=0) break; //可以取到了,跳出,当前
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(i!=j){ //表示从一个i杯子倒水到另一个j杯子,肯定不可能倒给自己啊
if(u.str[i]==0||u.str[j]==st[j]) continue; //被倒的是满的肯定不能倒啊
int num=min(st[j],u.str[i]+u.str[j])-u.str[j]; //选取倒的水量
node u2;
memcpy(&u2,&u,sizeof(u)); //将结构体复制过来 ,node u2=u?嘿嘿
u2.s=u.s+num;
u2.str[i]-=num;
u2.str[j]+=num; //倒水改变容量
if(!vis[u2.str[0]][u2.str[1]]){ //如果该状态未访问,则遍历
vis[u2.str[0]][u2.str[1]]=1;
Q.push(u2);
}
}
}
}
}
while(d>=0){ //千万不要while(d--),嘿嘿
if(ans[d]>=0){ //找到最接近的答案,不一定能倒满d
printf("%d %d\n",ans[d],d);
return;
}
d--;
}
}
int main(){
int T;
int a,b,c,d;
cin>>T;
while(T--){
cin>>a>>b>>c>>d;
solve(a,b,c,d);
}
return 0;
}
还有个题目就是丑数的
让你求第1500个只能整除的奇数只有2,3,5的数。当然就是1乘2,3,5,得到新的三个,然后在这个基础是扩展,必然是只能的到需要的数。很容易想到用set,但是可能会出现重复的情况,就要检测一次是否会重合,所以要用一个优先队列存储数字。肯定是优先取最小的。这里唯一一个priority_queue<ll,vector<ll>,greater<ll> >q;就是这个vector是不定长数组,然后greater是使队列中最小的在最上面,最大的在最下面。同理要是less的话就与此相反。下面附上代码
#include"queue"
#include"vector"
#include"set"
#include"iostream"
#include"cstdio"
typedef long long ll ;
using namespace std;//优先队列 priority_queue
set<ll >Q;
priority_queue<ll,vector<ll>,greater<ll> >q;
const int str[3]={2,3,5};
int main(){
Q.insert(1);
q.push(1);
for(int i=1;;i++){
ll m=q.top(); q.pop();
if(i==1500){
printf("The 1500'th ugly number is %lld.\n",m);
break;
}
for(int j=0;j<3;j++){
ll x=m*str[j];
if(!Q.count(x)){
q.push(x);
Q.insert(x);
}
}
}
return 0;
}
其实感觉还是蛮好理解的,就是取到第1500个的时候就可以输出的嘛
(第一次写,有点菜,见谅,哈哈\n);