• 【网络流24题】魔术球问题


    Description

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

    Input

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

    Output

    第一行是球数。

    Sample Input

    4

    Sample Output

    11

    Hint

    样例方案如下
    1 8
    2 7 9
    3 6 10
    4 5 11
    每一行表示一个柱子上的球
    n<=60 保证答案小于1600

    正解:最大流。

    考虑把球拆成两个点,动态连边,在残量网络上直接跑最大流。一个点连源点,一个点连汇点,在这个球之前的球,如果相加等于完全平方数,那么这个球连向汇点的点与之前那个球连向源点的点相连。从前往后枚举球,如果当前总球数-最大流>n,那么就不合法了。输出当前的前一个球即可。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <complex>
     5 #include <cstring>
     6 #include <cstdlib>
     7 #include <cstdio>
     8 #include <vector>
     9 #include <cmath>
    10 #include <queue>
    11 #include <stack>
    12 #include <map>
    13 #include <set>
    14 #define inf (1<<30)
    15 #define eps 1e-9
    16 #define il inline
    17 #define RG register
    18 #define ll long long
    19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    20 
    21 using namespace std;
    22 
    23 struct edge{ int nt,to,flow,cap; }g[1000010];
    24 
    25 int head[3210],d[3210],q[3210],n,S,T,flow,num=1;
    26 
    27 il int gi(){
    28     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    29     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
    30 }
    31 
    32 il void insert(RG int from,RG int to,RG int cap){ g[++num]=(edge){head[from],to,0,cap},head[from]=num; return; }
    33 
    34 il int bfs(RG int S,RG int T){
    35     memset(d,0,sizeof(d)); RG int h=0,t=1; q[t]=S,d[S]=1;
    36     while (h<t){
    37     RG int x=q[++h];
    38     for (RG int i=head[x];i;i=g[i].nt){
    39         RG int v=g[i].to;
    40         if (!d[v] && g[i].cap>g[i].flow){
    41         q[++t]=v,d[v]=d[x]+1;
    42         if (v==T) return 1;
    43         }
    44     }
    45     }
    46     return 0;
    47 }
    48 
    49 il int dfs(RG int x,RG int T,RG int a){
    50     if (x==T || !a) return a; RG int f,flow=0;
    51     for (RG int i=head[x];i;i=g[i].nt){
    52     RG int v=g[i].to;
    53     if (d[v]==d[x]+1 && g[i].cap>g[i].flow){
    54         f=dfs(v,T,min(a,g[i].cap-g[i].flow));
    55         g[i].flow+=f,g[i^1].flow-=f;
    56         flow+=f,a-=f; if (!a) return flow;
    57     }
    58     }
    59     if (!flow) d[x]=-1; return flow;
    60 }
    61 
    62 il int maxflow(RG int S,RG int T){ while (bfs(S,T)) flow+=dfs(S,T,inf); return flow; }
    63 
    64 il void work(){
    65     n=gi(),S=3201,T=3202;
    66     for (RG int ans=1;ans<=1600;++ans){
    67     insert(S,ans,1),insert(ans,S,0);
    68     for (RG int i=1;i<ans;++i)
    69         if (ans+i-(int)sqrt(ans+i)*(int)sqrt(ans+i)<eps)
    70         insert(i,ans+1600,1),insert(ans+1600,i,0);
    71     insert(ans+1600,T,1),insert(T,ans+1600,0);
    72     if (ans-maxflow(S,T)>n){ printf("%d
    ",ans-1); return; }
    73     }
    74     return;
    75 }
    76 
    77 int main(){
    78     File("ball");
    79     work();
    80     return 0;
    81 }
  • 相关阅读:
    日志记录到txt文件
    使用NuGet安装EntityFramework4.2
    Redis 安装与简单示例 <第一篇>
    时间加减时间段(年、月、日、分、秒)
    控件属性设置
    window.showModalDialog 与window.open传递参数的不同?
    如何进行js动态生成option?如何实现二级连动?
    System.Data.SqlClient.SqlError: 备份集中的数据库备份与现有的 'XXX' 数据库不同
    如何激发手机的高分辨率
    PHP--正则表达式和样式匹配--小记
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6434606.html
Copyright © 2020-2023  润新知