题目描述
«问题描述:
假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,…的球。
(1)每次只能在某根柱子的最上面放球。
(2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可放11 个球。
«编程任务:
对于给定的n,计算在n根柱子上最多能放多少个球。
输入输出格式
输入格式:
第1 行有1个正整数n,表示柱子数。
输出格式:
程序运行结束时,将n 根柱子上最多能放的球数以及相应的放置方案输出。文件的第一行是球数。接下来的n行,每行是一根柱子上的球的编号。
[分析]
网络流的解法网络上已经,很多了。这里讲一下贪心的解法。
贪心的解法,比网络流的好理解很多。特别简单
就是如果当前球能放在使用过的杆子上就放使用过的杆子上,如果不能再放没放过的。
并且,放球后在他下面的那个球必定比它小,所以不存在多种情况的分支(思考一下)。
所以模拟一边就好了。
[代码]
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<cmath>
#include<cstring>
using namespace std;
vector<int>v[57];
bool judge(int x)
{
int a = sqrt(x);
if (a*a == x)return 1;
else return 0;
}
int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
memset(v, 0, sizeof(v));
int cnt = 0;
int num = 0;
while (cnt <= n)
{
int flag = 0;
++num;
for (int i = 1; i <= cnt; i++)
{
if (judge(v[i][v[i].size() - 1] + num))
{
flag = 1;
v[i].push_back(num);
break;
}
}
if (flag == 0)
{
cnt++;
if (cnt > n)break;
v[cnt].push_back(num);
}
}
printf("%d\n", num-1);
for (int i = 1; i <= cnt; i++)
{
for (int j = 0; j < v[i].size(); j++)
{
if (j)printf(" ");
printf("%d", v[i][j]);
}
printf("\n");
}
}
}