1169: PIPI倒水
为什么ans[d]!=-1的时候,就可以return了?
因为使用小根堆,队列后面的节点的倒水量都比现在大,即使后面的节点也可以通过倒水出现d也没用了。
????????
哈哈哈哈哈处是两种代码不一样的地方。
我认为应该等到访问节点的时候,在设置vis为1,而不是在插入的时候,就设置为1。
因为访问节点A的时候插入节点C1,访问节点B的时候像插入节点C2.即使B在A之后,(C1和C2的三杯水相同)不代表A找到的C1一定比C2小吧?但是代码一会不让C2插入优先队列
但是代码2,就可以让C1和C2都插入,且C2会比C1先成为小根堆的堆顶,然后C2先更新ans。
#include <bits/stdc++.h>
using namespace std;
const int N=210;
int cap[3],d; //三个杯子的容量,目标值
struct node{
int water[3];
int dao;//达到当前节点,已经倒的水量
bool operator<(const node& a) const{
return dao>a.dao;
}
};
int vis[N][N]; //坐标x,y代表第一杯水和第二杯水的水量
int ans[N];
void bsf(priority_queue<node> q){
memset(ans,-1,sizeof(ans));
memset(vis,0,sizeof(vis));
ans[cap[2]]=0;ans[0]=0;
vis[0][0]=1;
while(!q.empty()){
auto now=q.top();
q.pop();
for(int i=0;i<3;i++){
if(ans[now.water[i]]==-1||ans[now.water[i]]>now.dao)
ans[now.water[i]]=now.dao;
}
if(ans[d]!=-1){
return;
}
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(i==j)
continue;
if(now.water[i]==0||now.water[j]==cap[j])
continue;
int pour=min(now.water[i],cap[j]-now.water[j]);
node next=now;
next.water[i]-=pour;
next.water[j]+=pour;
next.dao+=pour;
if(!vis[next.water[0]][next.water[1]])
{
vis[next.water[0]][next.water[1]]=1; //哈哈哈哈哈哈哈哈哈
q.push(next);
}
}
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d%d%d",&cap[0],&cap[1],&cap[2],&d);
node p; p.dao=0; p.water[2]=cap[2];p.water[0]=0;p.water[1]=0;
priority_queue<node> q; //关于倒水量的小根堆
q.push(p);
bsf(q);
for(int i=d;i>0;i--){
if(ans[i]!=-1){
printf("%d %d\n",ans[i],i);
break;
}
if(i==1){
printf("%d %d\n",0,0);
}
}
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int N=210;
int cap[3],d; //三个杯子的容量,目标值
struct node{
int water[3];
int dao;//达到当前节点,已经倒的水量
bool operator<(const node& a) const{
return dao>a.dao;
}
};
int vis[N][N]; //坐标x,y代表第一杯水和第二杯水的水量
int ans[N];
void bsf(priority_queue<node> q){
memset(ans,-1,sizeof(ans));
memset(vis,0,sizeof(vis));
ans[cap[2]]=0;ans[0]=0;
while(!q.empty()){
auto now=q.top();
q.pop();
vis[now.water[0]][now.water[1]]=1; //哈哈哈哈哈哈哈哈哈
for(int i=0;i<3;i++){
if(ans[now.water[i]]==-1||ans[now.water[i]]>now.dao)
ans[now.water[i]]=now.dao;
}
if(ans[d]!=-1){
return;
}
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(i==j)
continue;
if(now.water[i]==0||now.water[j]==cap[j])
continue;
int pour=min(now.water[i],cap[j]-now.water[j]);
node next=now;
next.water[i]-=pour;
next.water[j]+=pour;
next.dao+=pour;
if(!vis[next.water[0]][next.water[1]])
{
q.push(next);
}
}
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d%d%d",&cap[0],&cap[1],&cap[2],&d);
node p; p.dao=0; p.water[2]=cap[2];p.water[0]=0;p.water[1]=0;
priority_queue<node> q; //关于倒水量的小根堆
q.push(p);
bsf(q);
for(int i=d;i>0;i--){
if(ans[i]!=-1){
printf("%d %d\n",ans[i],i);
break;
}
if(i==1){
printf("%d %d\n",0,0);
}
}
}
return 0;
}

浙公网安备 33010602011771号