1. 粗略估计状态数不超过40401,枚举所有状态,来搜索最接近的d。
2. 本题的目标是倒水量最少,定义从状态s到状态v的边权为vol,类似dijkstra做法。
2. 本题的目标是倒水量最少,定义从状态s到状态v的边权为vol,类似dijkstra做法。
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <algorithm>
#include <sstream>
#include <utility>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <cctype>
#define CLEAR(a, b) memset(a, b, sizeof(a))
#define IN() freopen("in.txt", "r", stdin)
#define OUT() freopen("out.txt", "w", stdout)
#define LL long long
#define maxn 205
#define maxm 15
#define mod 1000000007
#define INF 1000000007
#define eps 1e-5
#define PI 3.1415926535898
using namespace std;
//-------------------------CHC------------------------------//
struct Node {
int v[3], d;
bool operator<(const Node &r) const {
return d > r.d;
}
};
int cap[3], ans[maxn];
bool vis[maxn][maxn];
void solve(int a, int b, int c, int d) {
cap[0] = a, cap[1] = b, cap[2] = c;
CLEAR(ans, -1);
CLEAR(vis, 0);
priority_queue<Node> q;
Node s;
s.v[0] = s.v[1] = 0, s.v[2] = c, s.d = 0;
q.push(s);
vis[0][0] = true;
while (q.size()) {
Node u = q.top(); q.pop();
for (int i = 0; i < 3; ++i)
if (ans[u.v[i]] == -1 || u.d < ans[u.v[i]])
ans[u.v[i]] = u.d;
if (ans[d] >= 0) break;
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 vol = min(cap[j], u.v[i] + u.v[j]) - u.v[j];
Node v;
memcpy(&v, &u, sizeof(u));
v.d = u.d + vol;
v.v[i] -= vol;
v.v[j] += vol;
if (!vis[v.v[0]][v.v[1]])
vis[v.v[0]][v.v[1]] = true, q.push(v);
}
}
while (d >= 0) {
if (ans[d] >= 0) {
printf("%d %d\n", ans[d], d);
return;
}
--d;
}
}
int main() {
int t;
cin >> t;
while (t--) {
int a, b, c, d;
cin >> a >> b >> c >> d;
solve(a, b, c, d);
}
return 0;
}