搜索不局限于图、迷宫,凡用状态来表示的,通常都可用。
故记录此题。
hint:由于此题答案求倒水量最少,而非倒水次数最少,因此,用优先队列来存储状态,比较的依据也是各状态的倒水量。如果是一般的求倒水步数,那就是一般的队列。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int maxn=205;
int vis[maxn][maxn],ans[maxn],cap[3];
struct Node{
int v[3],used;
bool operator < (const Node& rhs) const{
return used>rhs.used;
}
};
void update_ans(const Node& u){
for(int i=0;i<3;i++){
int d=u.v[i];
if(ans[d]<0||u.used<ans[d]) ans[d]=u.used;
}
}
void solve(int a,int b,int c,int d){
cap[0]=a;cap[1]=b;cap[2]=c;
memset(vis,0,sizeof(vis));
memset(ans,-1,sizeof(ans));
priority_queue<Node> q;
Node init;
init.used=0;
init.v[0]=init.v[1]=0;
init.v[2]=c;
q.push(init);
vis[0][0]=1;
while(!q.empty()){
Node u=q.top();
q.pop();
update_ans(u);//update ans
if(ans[d]>0) break;//ans[d]>0:got answer
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
if(i!=j){
if(u.v[i]==0||u.v[j]==cap[j]) continue;
int use=min(cap[j],u.v[i]+u.v[j])-u.v[j];
Node r;
memcpy(&r,&u,sizeof(u));
r.used+=use;
r.v[i]-=use;
r.v[j]+=use;
if(vis[r.v[0]][r.v[1]]!=1){
q.push(r);
vis[r.v[0]][r.v[1]]=1;
}
}
}
while(d>=0){
if(ans[d]>=0){
printf("%d %d\n",ans[d],d);
return;
}
d--;
}
}
int main()
{
int t,a,b,c,d;
scanf("%d",&t);
while(t--){
cin>>a>>b>>c>>d;
solve(a,b,c,d);
}
return 0;
}
mark:代码中,更新ans的条件,要么这个倒水量之前没达到过,要么更少的排水量出现。