题目链接如下:
刘汝佳用优先队列来做的,更简洁一些。
我的代码如下(mp是将一个状态映射到水的总流量):
#include <cstdio>
#include <utility>
#include <map>
#include <deque>
// #define debug
int T, d, tot, dMax;
std::map<std::pair<int, int>, int> mp;
int v[3], cap[3], s[6];
int start[] = {0, 0, 1, 1, 2, 2};
int end[] = {1, 2, 0, 2, 0, 1};
std::deque<std::pair<int, int>> dq;
void move(int i, int j){
if (v[i] == 0 || v[j] == cap[j]){
return;
}
int tempTot = mp[{v[0], v[1]}];
int temp = std::min(v[i], cap[j] - v[j]);
tempTot += temp;
v[i] -= temp;
v[j] += temp;
if (v[i] == d || v[j] == d){
if (dMax < d || (dMax == d && tempTot < tot)){
dMax = d;
tot = tempTot;
mp[{v[0], v[1]}] = tempTot;
}
return;
}
if (v[i] < d && (v[i] > dMax || (v[i] == dMax && tempTot < tot))){
dMax = v[i];
tot = tempTot;
}
if (v[j] < d && (v[j] > dMax || (v[j] == dMax && tempTot < tot))){
dMax = v[j];
tot = tempTot;
}
if (mp.find({v[0], v[1]}) == mp.end() || mp[{v[0], v[1]}] > tempTot){
mp[{v[0], v[1]}] = tempTot;
dq.push_back({v[0], v[1]});
}
}
int main(){
#ifdef debug
freopen("0.txt", "r", stdin);
freopen("1.txt", "w", stdout);
#endif
scanf("%d", &T);
while (T--){
scanf("%d %d %d %d", cap, cap + 1, cap + 2, &d);
if (cap[2] == d){
printf("0 %d\n", d);
continue;
}
mp.clear();
dq.clear();
mp[{0, 0}] = 0;
dq.push_back({0, 0});
dMax = cap[2] < d ? cap[2] : 0;
tot = 0;
while (!dq.empty()){
std::pair<int, int> init = dq.front();
dq.pop_front();
for (int i = 0; i < 6; ++i){
v[0] = init.first;
v[1] = init.second;
v[2] = cap[2] - v[0] - v[1];
move(start[i], end[i]);
}
}
printf("%d %d\n", tot, dMax);
}
#ifdef debug
fclose(stdin);
fclose(stdout);
#endif
return 0;
}