P2474 [SCOI2008] 天平

Sol

题面只给出了两两之间的大小关系,然后需要你求出如果给定两个砝码 \(A,B\),然后你再挑选两个与 \(A,B\) 不同的砝码放到天平上,问有分别有几种方式天平向左,平衡,向右。

考虑记录两个砝码之间的差的最大值和最小值,分别记作 \(f_{i,j},g_{i,j}\),对于一个途径的 \(k\)(就是 \(i,j\) 都与 \(k\) 这个砝码比较以后得到的结果),\(f_{i,j}\gets_{\min(f_{i,j},\max(f_{i,k},f_{k,j}))}\)\(g\) 同理。

统计答案的时候直接枚举所选的两个砝码,然后注意两个砝码的大小之差有没有交集即可。

Code

#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define eb emplace_back
#define pf push_front
#define desktop "C:\\Users\\incra\\Desktop\\"
#define IOS ios :: sync_with_stdio (false),cin.tie (0),cout.tie (0)
#define debug(x) cerr << #x << ' ' << x << endl
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int,int> PII;
const int dx[] = {1,0,-1,0},dy[] = {0,-1,0,1};
template <typename T1,typename T2> bool tomax (T1 &x,T2 y) {
	if (y > x) return x = y,true;
	return false;
}
template <typename T1,typename T2> bool tomin (T1 &x,T2 y) {
	if (y < x) return x = y,true;
	return false;
}
LL power (LL a,LL b,LL p) {
	if (!a) return 0;
	LL ans = 1;
	while (b) {
		if (b & 1) ans = ans * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return ans;
}
int fastio = (IOS,0);
#define endl '\n'
#define puts(s) cout << (s) << endl
const int N = 60;
int n,a,b;
int f[N][N],g[N][N];
void mian () {
	cin >> n >> a >> b;
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= n;j++) {
			char ch;
			cin >> ch;
			if (i == j && ch == '=') f[i][j] = g[i][j] = 0;
			else if (ch == '+') f[i][j] = 2,g[i][j] = 1;
			else if (ch == '-') f[i][j] = -1,g[i][j] = -2;
			else if (ch == '?') f[i][j] = 2,g[i][j] = -2;
		}
	}
	for (int k = 1;k <= n;k++) {
		for (int i = 1;i <= n;i++) {
			for (int j = 1;j <= n;j++) {
				tomin (f[i][j],f[i][k] + f[k][j]);
				tomax (g[i][j],g[i][k] + g[k][j]);
			}
		}
	}
	int ans1 = 0,ans2 = 0,ans3 = 0;
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j < i;j++) {
			if (i == a || i == b || j == a || j == b) continue;
			if (g[a][i] > f[j][b] || g[a][j] > f[i][b])	ans1++;
			if (g[a][i] == f[a][i] && g[a][i] == g[j][b] && g[j][b] == f[j][b]) ans2++;
			else if (g[b][i] == f[b][i] && g[b][i] == g[j][a] && g[j][a] == f[j][a]) ans2++;
			if (f[a][i] < g[j][b] || f[a][j] < g[i][b]) ans3++;
		}
	}
	cout << ans1 << ' ' << ans2 << ' ' << ans3 << endl;
}
int main () {
	int T = 1;
	// cin >> T;
	while (T--) mian ();
	return 0;
}
posted @ 2025-05-17 19:19  incra  阅读(16)  评论(0)    收藏  举报