J - Fill (UVA - 10603)
阿新 • • 發佈:2018-03-07
amp pop 標記 思路 operator OS string sta post
- 題目大意
有三個已知體積但不知刻度的杯子,前兩個杯子中初始時沒有水,第三個裝滿水,問是否可以倒出d升水,如果倒不出,則倒出一個最大的d’,使得d’<=d,並且在這個過程中要求總倒水量最少。
- 解題思路
可以用DFS加上優先隊列來解決,以前兩個杯子中的水量作為標記狀態。只不過這次不是要求的最求最少步數,而是要求最少倒水量即可。
- 代碼
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cstring> #include<stack> #include<queue> using namespace std; int maps[500][500]; int cnt[500]; struct Edge { int m[3],sum; Edge(int a,int b,int c,int s) { m[0]=a,m[1]=b,m[2]=c,sum=s; } bool operator <(const Edge &rhs)const{ return sum>rhs.sum; } }; void bfs(int a,int b,int c,int d) { int num[3]={a,b,c}; priority_queue<Edge>q; memset(maps,0,sizeof(maps)); memset(cnt,-1,sizeof(cnt)); maps[0][0]=1; q.push(Edge(0,0,c,0)); while(!q.empty()) { Edge u=q.top(); q.pop(); for(int i=0;i<3;i++) { if(cnt[u.m[i]]<0||u.sum<cnt[u.m[i]]) cnt[u.m[i]]=u.sum; } if(cnt[d]>=0) break; for(int i=0;i<3;i++) { if(u.m[i]==num[i]) continue; for(int j=0;j<3;j++) { if(i==j||u.m[j]==0) continue; int mid=min(num[i],u.m[j]+u.m[i])-u.m[i]; Edge tmp=u; tmp.sum+=mid; tmp.m[i]+=mid; tmp.m[j]-=mid; if(!maps[tmp.m[0]][tmp.m[1]]) { maps[tmp.m[0]][tmp.m[1]]=1; q.push(tmp); } } } } while(d>=0) { if(cnt[d]>=0) { printf("%d %d\n",cnt[d],d); return; } --d; } } int main() { int a,b,c,d; int n; scanf("%d",&n); while(n--) { scanf("%d%d%d%d",&a,&b,&c,&d); bfs(a,b,c,d); } return 0; }
J - Fill (UVA - 10603)