魔术球问题

传送门:

题解区的玄学公式:球的个数:(n*(n+2)+(n&1)-2)/2

既然能直接求出球的个数那么就会有贪心法emmm

#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <cmath>
using namespace std;
#define ll long long
#define re register
const int N=1e7+10;
const int inf=1e9;
inline void read(int &a)
{
    a=0;
    int d=1;
    char ch;
    while(ch=getchar(),ch>'9'||ch<'0')
        if(ch=='-')
            d=-1;
    a=ch^48;
    while(ch=getchar(),ch>='0'&&ch<='9')
        a=(a<<3)+(a<<1)+(ch^48);
    a*=d;
}
int a[60][60];
int f(int x){return x*x;}
int main()
{
    int n,m;
    read(n);
    m=(n*(n+2)+(n&1)-2)/2;
    printf("%d
",m);
    for(re int i=1;i<=m;i++)
        for(re int j=1;j<=n;j++)
        {
            int x=a[j][a[j][0]];
            if(!x||f(int(sqrt(x+i)))==x+i)
            {
                a[j][++a[j][0]]=i;
                break;
            }
        }
    for(re int i=1;i<=n;i++)
    {
        for(re int j=1;j<=a[i][0];j++)
            printf("%d ",a[i][j]);
        putchar('
');
    }
    return 0;
}

但是作为一道网络流24题的题目,我觉得应该要用网络流的方法写才能锻炼自己,如果对最大流模板熟悉,那么这道题的难点只是建图。

这题只要把一个点分割成两个点,然后建图就ok了

#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <cmath>
using namespace std;
#define ll long long
#define re register
const int N=1e6+10;
const int inf=1e9;
inline void read(int &a)
{
    a=0;
    int d=1;
    char ch;
    while(ch=getchar(),ch>'9'||ch<'0')
        if(ch=='-')
            d=-1;
    a=ch^48;
    while(ch=getchar(),ch>='0'&&ch<='9')
        a=(a<<3)+(a<<1)+(ch^48);
    a*=d;
}
struct note
{
    int next,v,dis;
}edge[N];
int cnt=-1,head[N],n,dep[N],p[60],nxt[N];
bool vis[N];
inline void add(int u,int v,int dis)
{
    edge[++cnt].next=head[u];
    edge[cnt].v=v;
    edge[cnt].dis=dis;
    head[u]=cnt;
    edge[++cnt].next=head[v];
    edge[cnt].v=u;
    edge[cnt].dis=0;
    head[v]=cnt;
}
queue <int> q;
inline bool bfs(int s,int t)
{
    memset(dep,0x7f,sizeof(dep));
    while(!q.empty())
        q.pop();
    dep[s]=0;
    q.push(s);
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(re int i=head[now];i!=-1;i=edge[i].next)
        {
            if(dep[edge[i].v]>inf&&edge[i].dis)
                dep[edge[i].v]=dep[now]+1,q.push(edge[i].v);
        }
    }
    if(dep[t]<inf)
        return 1;
    return 0;
}
inline int dfs(int now,int t,int limit)
{
    if(now==t)
        return limit;
    for(re int i=head[now];i!=-1;i=edge[i].next)
    {
        if((dep[edge[i].v]==dep[now]+1)&&edge[i].dis)
        {
            int f=dfs(edge[i].v,t,min(limit,edge[i].dis));
            if(f>0)
            {
                edge[i].dis-=f;
                edge[i^1].dis+=f;
                if(now!=0&&edge[i].v!=N-1)
                    nxt[now>>1]=edge[i].v>>1;
                return f;
            }
        }
    }
    return 0;
}
inline int dinic(int s,int t)
{
    int flow=0;
    while(bfs(s,t))
    {
        while(int di=dfs(s,t,inf))
            flow+=di;
    }
    return flow;
}
int main()
{
    memset(head,0xff,sizeof(head));
    int s=0,t=N-1,k;
    n=0;
    read(k);
    int now=0;
    while(now<=k)
    {
        n++;
        add(s,(n<<1),1);
        add((n<<1)|1,t,1);
        for(re int i=sqrt(n)+1;i*i<(n<<1);i++)
            add((i*i-n)<<1,(n<<1)|1,1);
        int x=dinic(s,t);
        if(!x)
            p[++now]=n;
    }
    printf("%d
",n-1);
    for(re int i=1;i<=k;i++)
    {
        if(vis[p[i]])
            continue;
        int x=p[i];
        vis[x]=1;
        while(x!=0)
        {
            printf("%d ",x);
            x=nxt[x];
            vis[x]=1;
        }
        putchar('
');
    }
    return 0;
}
原文地址:https://www.cnblogs.com/acm1ruoji/p/11045105.html