UVA 10603:倒水
BFS类题目,尝试用DFS,无奈会超时。DFS不能摆脱的命运啊,,,下面给出运行 结果正确但TL的DFS代码;AC 0MS的BFS代码。DFS代码(超时):#include<iostream>#include<cstdio>#include<algorithm>#include<str...
·
题目:https://vjudge.net/problem/UVA-10603
需要注意的是:同一状态可以多次得到,但是到水量可能不同。有两种方法处理:
1.在每次判断当前状态是否存在时,判断当前状态即使存在,倒水量是否更小
2.用优先队列,每次先转移到水量较少的状态。
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<map>
#include<unordered_map>
#include<unordered_set>
#include<set>
#include<stack>
#include<sstream>
using namespace std;
const int maxn = 205;
int a, b, c, d, d1, summin, summin1, ok;
int vis[maxn][maxn], litre[3];
struct node {
int w[3],sum;
bool operator < (const node & nd) const{
return sum > nd.sum;
}
};
void bfs() {
priority_queue<node> q;
q.push(node({ 0,0,c ,0 }));
vis[0][0] = 1;
while (!q.empty()) {
node nd = q.top();
q.pop();
if (nd.w[0] == d || nd.w[1] == d || nd.w[2] == d)
{
ok = 1;
summin = min(summin, nd.sum);
break;
}
for (int i = 0; i < 3; i++)
if (nd.w[i] >= d1 && nd.w[i] < d)
{
if (nd.w[i] == d1)
{
summin1 = min(summin1, nd.sum);
}
else
{
d1 = nd.w[i];
summin1 = nd.sum;
}
}
node temp;
for (int i = 0; i < 3; i++)
{
if (nd.w[i] > 0)
{
for (int j = 0; j < 3; j++)
{
temp = nd;
if (j != i && nd.w[j]!=litre[j])
{
if (nd.w[i] >= litre[j] - nd.w[j] )
{
temp.w[i] = nd.w[i] - (litre[j] - nd.w[j]);
temp.w[j] = litre[j];
temp.sum += litre[j] - nd.w[j];
}
else
{
temp.w[i] = 0;
temp.w[j] = nd.w[j] + nd.w[i];
temp.sum += nd.w[i];
}
if (!vis[temp.w[0]][temp.w[1]])
{
q.push(temp);
vis[temp.w[0]][temp.w[1]] = 1;
}
}
}
}
}
}
}
int main() {
int t;
cin >> t;
while (t--) {
cin >> a >> b >> c >> d;
litre[0] = a; litre[1] = b; litre[2] = c;
summin = summin1 = 0x3f3f3f3f;
ok = d1 = 0;
memset(vis, 0, sizeof(vis));
bfs();
if (ok)
cout << summin << " " << d << endl;
else
cout << summin1 << " " << d1 << endl;
}
return 0;
}
DFS:
#include<iostream>
#include<limits.h>
#include<algorithm>
#include<string.h>
using namespace std;
//v表示容器的毫升,st表示各容器每次注水状态
int st[3], v[3], vis[201][201][201];
//a,b,c表示容器的毫升,d1表示目前最接近d的毫升数
int a, b, c, d, d1;
int flag, ans0, ans1;
void dfs(int sumv)
{
if (count(st, st + 3, d))
{
if(sumv < ans0)
ans0 = sumv;
flag = 1;
return;
}
if (flag && sumv >= ans0)
return;
if (!flag)//若达不到d,则找一个最接近d的注水量,并记录最小注水
{
for (int i = 0; i < 3; i++)
{
if (st[i] < d && st[i] >= d1)
{
if (d1 == st[i])
ans1 = min(ans1, sumv);
else
{
d1 = st[i];
ans1 = sumv;
}
}
}
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (i != j && st[i] && st[j] != v[j]) //由i倒入j,i不空且j不满
{
//tmp系列参数用于后面的回溯
int tmp_i = st[i];
int tmp_j = st[j];
int tmp_v;
if (st[i] + st[j] < v[j])
{
tmp_v = st[i];
st[j] = st[i] + st[j];
st[i] = 0;
}
else
{
tmp_v = v[j] - st[j];
st[i] = st[i] - tmp_v;
st[j] = v[j];
}
if (!vis[st[0]][st[1]][st[2]])
{
vis[st[0]][st[1]][st[2]] = 1;
dfs(sumv + tmp_v);
vis[st[0]][st[1]][st[2]] = 0;
}
st[i] = tmp_i;
st[j] = tmp_j;
}
}
}
return;
}
int main()
{
int num;
cin >> num;
while (num--)
{
flag = 0;
d1 = 0;
ans0 = ans1 = INT_MAX;
memset(vis, 0, sizeof(vis));
cin >> a >> b >> c >> d;
v[0] = a; v[1] = b; v[2] = c;
st[0] = 0; st[1] = 0; st[2] = c;
vis[0][0][c] = 1;
dfs(0);
flag == 1 ? (cout << ans0 << " " << d << endl): (cout << ans1 << " " << d1 << endl);
}
}
//56 184 180 16
BFS:
#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
struct state
{
int water[3];
int sumv;
}st, st1;
queue<state> q;
int d;
int v[3], minvolume[201], vis[201][201]; //不必用三维vis,因为已知前2个元素不同,第3个必不同
void cmp(state st1)
{
for (int k = 0; k < 3; k++)
{
if (minvolume[st1.water[k]] < 0)
minvolume[st1.water[k]] = st1.sumv;
else
minvolume[st1.water[k]] = minvolume[st1.water[k]] > st1.sumv ? st1.sumv : minvolume[st1.water[k]];
}
}
void bfs()
{
q.push(st);
while (!q.empty())
{
st = q.front();
q.pop();
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (i == j)
continue;
st1 = st;
//i杯倒入j杯,若i杯水量小于j杯剩余水量,倒水量为st.water[i]
// 若i杯水量小于j杯剩余水量,倒水量为w[j] - st.water[j]
int curv = v[j] - st.water[j] > st.water[i] ? st.water[i] : v[j] - st.water[j];
st1.water[i] -= curv;
st1.water[j] += curv;
//如果此次水量与之前不同|| 现在3个杯中容量所需的倒水量小于minvolume中记录
if (!vis[st1.water[0]][st1.water[1]] || minvolume[st1.water[0]] > (st.sumv + curv) || minvolume[st1.water[1]] > (st.sumv + curv) || minvolume[st1.water[2]] > (st.sumv + curv))
{
vis[st1.water[0]][st1.water[1]] = 1;
st1.sumv = st.sumv + curv;
cmp(st1);
q.push(st1);
}
}
}
}
}
int main()
{
int num;
cin >> num;
while (num--)
{
cin >> v[0] >> v[1] >> v[2] >> d;
memset(vis, 0, sizeof(vis));
memset(minvolume, -1, sizeof(minvolume));
st.water[0] = 0;
st.water[1] = 0;
st.water[2] = v[2];
st.sumv = 0;
minvolume[0] = minvolume[st.water[2]] = 0;
vis[0][0] = 1;
bfs();
for (int i = d; i >= 0; i--) {
if (minvolume[i] >= 0) {
cout << minvolume[i] << " " << i << endl;
break;
}
}
}
return 0;
}
更多推荐
已为社区贡献3条内容
所有评论(0)