一名苦逼的OIer,想成为ACMer

Iowa_Battleship

洛谷1268 树的重量

原题链接

\(n = 2\)时,显然答案为\(M(1, 2)\)
\(n = 3\)时,我们固定\(M(1, 2)\),考虑\(3\)的位置。

如图,\(3\)的位置肯定是从\((1,2)\)中分支出来的,所以答案为\(M(1, 2) + \dfrac{M(1, 3) + M(2, 3) - M(1, 2)}{2}\)
于是我们可以拓展到\(n\)的情况,第\(n\)个点可以从\((1, 2 \to n - 1)\)中分支出来,然后我们可以贪心地选择,即这条分支的长为\(\min \limits _{i = 2} ^ {n - 1} \{ \dfrac{M(1, n) + M(i, n) - M(1, i)}{2} \}\)
所以最后的答案为$$M(1, 2) + \sum \limits _{i = 3} ^ {n} \min \limits _{j = 2} ^ {i - 1} { \dfrac{M(1, i) + M(j, i) - M(1, j)}{2} }$$

#include<cstdio>
using namespace std;
const int N = 31;
int a[N][N];
inline int re()
{
	int x = 0;
	char c = getchar();
	bool p = 0;
	for (; c < '0' || c > '9'; c = getchar())
		p |= c == '-';
	for (; c >= '0' && c <= '9'; c = getchar())
		x = x * 10 + c - '0';
	return p ? -x : x;
}
inline int minn(int x, int y){ return x < y ? x : y; }
int main()
{
	int i, j, n, s, mi;
	while (1)
	{
		n = re();
		if (!n)
			return 0;
		for (i = 1; i < n; i++)
			for (j = i + 1; j <= n; j++)
				a[i][j] = re();
		s = a[1][2];
		for (i = 3; i <= n; i++)
		{
			mi = 1e9;
			for (j = 2; j < i; j++)
				mi = minn(mi, a[1][i] + a[j][i] - a[1][j]);
			s += mi >> 1;
		}
		printf("%d\n", s);
	}
	return 0;
}

posted on 2018-11-03 10:13  Iowa_Battleship  阅读(118)  评论(0编辑  收藏  举报

导航