码迷,mamicode.com
首页 > 其他好文 > 详细

「Luogu2765」[网络流24题] 魔术球问题

时间:2018-09-10 13:31:35      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:define   main   getch   地方   pac   har   整数   编程   include   

->戳我进原题

[网络流24题] 魔术球问题


时空限制:1000ms / 128MB


问题描述

假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球。
(1)每次只能在某根柱子的最上面放球。
(2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可放11 个球。

编程任务

对于给定的n,计算在n根柱子上最多能放多少个球。

输入格式

第1 行有1个正整数n,表示柱子数。

输出格式

程序运行结束时,将n 根柱子上最多能放的球数以及相应的放置方案输出。文件的第一行是球数。接下来的n行,每行是一根柱子上的球的编号。

输入样例

4

输出样例

11
1 8
2 7 9
3 6 10
4 5 11

说明

4<=n<=55

分析

魔术球问题 网络流的经典例题

然而本蒟蒻并不会写网络流做法

所以今天我向大家介绍一种较为朴素的做法 贪心

本题的数据给的\(55\) 所以我们尽可以写O\(3\) O\(4\)算法

于是我便有了贪心的念头

查看本题题意不难发现 为了使柱子尽可能填满且尽可能多填数

可以把本题分为两种操作

(1)如果当前柱子有可以放置使前后成为平方数的位置 则放置

(2)如果当前没有可放置位置 开一个新柱子 将该球放到新柱子的第一项

这样我们就可以贪心辣~ 但是我们有几个地方需要注意

a要注意边界是柱子开到n个 如果不判边界会使程序进入死循环

b由于球号是自增的 所以在输出最大球号是要输出最后判断停止的球号-1

c在循环判断放球的时候可以找到位置立刻break 这样可以达到一个剪枝的效果

好辣 看到这里有没有觉得其实这个题很简单呢

我建议你们自己写写 如果还写不出来的话再看下面的完整代码

代码

#include<cstdio>
#include<cctype>
#include<cmath>
#define rg register  
using namespace std;
const int N =56;
int f[N][10001],ball,book[N];//book来存每一个柱子有几个数
int n,cnt=1,spot;
inline int read(){
    rg int f=0,x=0;
    rg char ch=getchar();
    while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
    while(isdigit(ch))  x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?-x:x;
}
inline bool jud(rg int x){//判断是否为平方数
    rg int i=(int)sqrt(x);
    if(i*i==x)  return true;
    else    return false;
}
signed main(){
    n=read();
    while(cnt<=n){
        ball++;
        spot=0;
        for(rg int i=1; i<=cnt; ++i){
            if(jud(ball+f[i][book[i]])){//如果能找到
                book[i]++;
                f[i][book[i]]=ball;
                break;
            }
            spot++;//每找一个循环都标记一下
        }
        if(spot==cnt){//走完所有循环都没找到
            cnt++;
            f[cnt][1]=ball;
            book[cnt]=1;
        }
    }
    printf("%d\n",ball-1);//一定要-1!!
    for(rg int i=1; i<cnt; ++i){//i<cnt是因为现在的cnt是多出来的一个ball
        for(rg int j=1; j<=book[i]; ++j)
            printf("%d ",f[i][j]);
        printf("\n");
    }
    return 0;
}

后话

当然网络流还有其它的题可以拿诸如此类的贪心做

既然分在了网络流大家最好还是要尝试一下网络流的做法

不要浪费每一道好题

「Luogu2765」[网络流24题] 魔术球问题

标签:define   main   getch   地方   pac   har   整数   编程   include   

原文地址:https://www.cnblogs.com/horrigue/p/9618379.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!