CF EDU 120 E - Math Test

E - Math Test

拆绝对值

要求 \(\sum\limits_{i=1}^n|r_i-x_i|\) 的最大值,可以将绝对值拆开,对于每一个 i,若 \(r_i>=x_i\), 设 \(sgn[i] = 1\). 否则设为 \(sgn[i]=-1\)\(\sum\limits_{i=1}^n|r_i-x_i|=\sum\limits_{i=1}^nsgn[i]*r_i-sgn[i]*x_i\)

由于 n 很小,可枚举这 \(2^n\) 种符号,此时 \(\sum\limits_{i=1}^nsgn[i]*x[i]\) 已经固定,只需求 \(\sum\limits_{i=1}^nsgn[i]*r[i]\) 的最大值,\(r[i]=\sum\limits_{j=1}^m p[j]*(s[i][j] == 1)\), 因此 \(\sum\limits_{i=1}^nsgn[i]*r[i]=\sum\limits_{j=1}^mp[j]\sum\limits_{i=1}^nsgn[i]*(s[i][j]==1)\)

所以贪心的对于最小的 \(\sum\limits_{i=1}^nsgn[i]*(s[i][j]==1)\) 这道题的分值就给 1,第二小的给 2 ...

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 11, M = 1e4 + 10;
ll x[N], p[M];
int sgn[N];
int n, m;
string str[N];

int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while(T--)
	{
		cin >> n >> m;
		for (int i = 0; i < n; i++)
			cin >> x[i];
		for (int i = 0; i < n; i++)
			cin >> str[i];
		for (int i = 0; i < m; i++)
			p[i] = i + 1;
		ll ans = 0;
		for (int s = 0; s < 1 << n; s++)
		{
			for (int i = 0; i < n; i++)
			{
				if (s >> i & 1)
					sgn[i] = 1;
				else
					sgn[i] = -1;
			}
			vector<PII> vt;
			for (int j = 0; j < m; j++)
			{
				int t = 0;
				for (int i = 0; i < n; i++)
					t += sgn[i] * (str[i][j] == '1');
				vt.push_back({t, j});
			}
			sort(vt.begin(), vt.end());
			ll now = 0;
			for (int i = 0; i < m; i++)
				now += (i + 1) * vt[i].first;
			for (int i = 0; i < n; i++)
				now -= sgn[i] * x[i];
			if (now > ans)
			{
				ans = now;
				for (int i = 0; i < m; i++)
					p[vt[i].second] = i + 1;
			}
		}
		for (int i = 0; i < m; i++)
			cout << p[i] << " ";
		cout << endl;
	}
	return 0;
}

posted @ 2022-05-12 20:26  hzy0227  阅读(19)  评论(0编辑  收藏  举报