P2474 题解
liangbowen · · 题解
前言
题目传送门!
更好的阅读体验?
差分约束。
update:修改了
思路
预处理
维护两个数组
我们分类讨论:
差分约束
统计完基本信息后,就可以差分约束了。
由于数据范围很小(
转移:(
反向取上下界,应该很容易理解吧。
统计答案
对于所有
同样是分类讨论:
-
如果
mn_{A, i} > mx_{j, B} 或者mn_{A, j} > mx_{i, B} ,说明左边有可能重。 -
如果
mn_{A, i} = mx_{A, i} = mn_{j, B} = mx_{j, B} ,说明有可能相等; 同理,如果mn_{B, i} = mx_{B, i} = mn_{j, A} = mx_{j, A} ,也有可能相等; -
与左边重的情况相反,如果
mn_{A, i} < mx_{j, B} 或者mn_{A, j} < mx_{i, B} ,说明右边有可能重。
统计好后输出即可。这道题就完美的做完啦!
完整代码
略微压行,凑合着看看吧,应该很容易看懂。
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 55;
int n, A, B;
int maxd[N][N], mind[N][N]; //maxd[i][j] 或 mind[i][j] 表示:砝码 i 与砝码 j 重量差值 的最值。
void Input()
{
scanf("%d%d%d", &n, &A, &B);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
char x;
cin >> x;
if (i == j || x == '=') maxd[i][j] = mind[i][j] = 0; //别忘了:同一块砝码,最值都是 0。
else if (x == '+') maxd[i][j] = 2, mind[i][j] = 1; //差值最大:a[i]=3,a[j]=1。最小:a[i]=2,a[j]=1。
else if (x == '-') maxd[i][j] = -1, mind[i][j] = -2; //恰好与上面反过来。
else if (x == '?') maxd[i][j] = 2, mind[i][j] = -2; //差值最大:a[i]=3,a[j]=1。最小:a[i]=1,a[j]=3。
}
}
void Floyd() //差分约束
{
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
maxd[i][j] = min(maxd[i][j], maxd[i][k] + maxd[k][j]),
mind[i][j] = max(mind[i][j], mind[i][k] + mind[k][j]);
}
void Output()
{
int lcnt = 0, ecnt = 0, rcnt = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j < i; j++)
{
//要保证 i 与 j 均不是给定砝码。
if (i == A || i == B) break;
if (j == A || j == B) continue;
if (mind[A][i] > maxd[j][B] || mind[A][j] > maxd[i][B]) lcnt++;
if (mind[A][i] == maxd[A][i] && mind[A][i] == mind[j][B] && mind[j][B] == maxd[j][B]) ecnt++;
else if (mind[B][i] == maxd[B][i] && mind[B][i] == mind[j][A] && mind[j][A] == maxd[j][A]) ecnt++;
if (maxd[A][i] < mind[j][B] || maxd[A][j] < mind[i][B]) rcnt++;
}
printf("%d %d %d", lcnt, ecnt, rcnt);
}
int main()
{
//程序三段式,十分清晰美观。
Input();
Floyd();
Output();
return 0;
}
希望能帮助到大家!