题解 洛谷P2765 网络流24题.02【魔术球问题】

\(\huge\mathbb{DESCRIPTION}\)
编号:洛谷\(P2765\)\(LOJ6003\)(与洛谷上本题输出格式有不同)
算法:网络最大流\(\mathbb{OR}\)贪心
来源:网络流\(24\)
\(\huge\mathbb{SOLUTION}\)
这道题目我们可以用网络最大流来解决。
但是,我觉得贪心也可以啊。
事实证明,贪心是对的
那么我们先来考虑一下怎么贪心。
不难想到一个贪心:放一个球在已经有的柱子上,比再开一个新柱子更优化
那么考虑如何证明这个贪心的正确性。
设现在已经放好了\(A_1,A_2,A_3,A_4,\ldots,A_i,\ldots,A_j,\ldots,A_k,\ldots\)
设现在我要开始放\(A_x\)了。
那么我现在有两中策略:

  • 在一个可以和\(A_x\)组成完全平方数的数\(A_i\)上面放。即:\(A_1,A_2,A_3,A_4,\ldots,A_x,\ldots,A_j,\ldots,A_k,\ldots\)
  • 新开一个柱子。即:\(A_1,A_2,A_3,A_4,\ldots,A_i,\ldots,A_j,\ldots,A_k,\ldots,A_x\)

为了比较,我们再继续往后考虑\(A_{x+1}\)
\(A_i\)\(A_x\)的和等于\(a^2\)
易证,\(A_i+1\)不能放在\(A_i\)上面。
考虑到这一点,后面就迎刃而解了。
也可以感性理解一下啦\(\ldots\)

插播广告

读者:万恶的作者!
作者:懒得证了\(\ldots\)

回归正题

所以我们的贪心是正确的。
\(\huge\mathbb{CODE}\)

#include<bits/stdc++.h>
using namespace std;
int N;
int Ans;
int Count;
int Square[4001];
vector<int>Column[56];
int main(void)
{
	register int i,j;
	cin>>N;
	for(i=1;i<=55;i++)
	{
		Square[i*i]=true;
	}
	while(true)
	{
		for(i=1;i<=Count;i++)
		{
			if(Square[Column[i][Column[i].size()-1]+Ans])
			{
				Column[i].push_back(Ans);
				i=0;
				Ans++;
				continue;
			}
		}
		if(Count<N)
		{
			Count++;
			Column[Count].push_back(Ans);
			Ans++;
		}
		else
		{
			break;
		}
	}
	Ans--;
	cout<<Ans<<endl;
	for(i=1;i<=N;i++)
	{
		for(j=0;j<Column[i].size();j++)
		{
			if(!Column[i][j])
			{
				continue;
			}
			cout<<Column[i][j]<<' ';
		}
		cout<<endl;
	}
    return 0;
}
posted @ 2020-08-15 15:18  Bushuai_Tang  阅读(97)  评论(0编辑  收藏  举报