[网络流24题]魔术球问题(简化版

396. [网络流24题]魔术球问题(简化版

★★☆   输入文件:balla.in   输出文件:balla.out   简单对比
时间限制:1 s   内存限制:128 MB

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

´数据输入: 
文件第1 行有 1个正整数n,表示柱子数。 
´结果输出: 
文件的第一行是球数。

数据规模

n<=60  保证答案小于1600

输入文件示例

4

输出文件示例

11

方案如下

1 8 
2 7 9 
3 6 10 
4 5 11

每一行表示一个柱子上的球

 

本题原版

 

最小路径覆盖=总点数-最大匹配

最大匹配可以用dinic 来求。其实最小路径覆盖数就相当于是柱子数

 

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int N=3510;
const int INF=1e9;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct edge{
    int v,nxt,f;
}e[N*50];
int hd[N],tot=1;
void add_edge(int u,int v,int c){
    e[++tot].v=v;e[tot].nxt=hd[u];e[tot].f=c;hd[u]=tot;return;
}
void insert(int u,int v,int c){
    add_edge(u,v,c);add_edge(v,u,0);
}
int n,m,S,T;
int d[N];
bool BFS(){
    memset(d,0,sizeof d);
    queue<int>q;
    q.push(S);
    d[S]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=hd[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(e[i].f && !d[v]){
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }
    return d[T];
}
int DFS(int u,int lim){
    if(u==T)return lim;
    int tmp,f=0;
    for(int i=hd[u];i;i=e[i].nxt){
        int v=e[i].v;
        if(d[v]==d[u]+1&&e[i].f){
            tmp=DFS(v,min(lim,e[i].f));
            e[i].f-=tmp;
            e[i^1].f+=tmp;
            f+=tmp;
            lim-=tmp;
            if(!lim)return f;
        }
    }
    d[u]=0;
    return f;
}
int Dinic(){
    int res=0;
    while(BFS())res+=DFS(S,INF);
    return res;
}
int main(){
    freopen("balla.in","r",stdin);
    freopen("balla.out","w",stdout);
    n=read();m=0;
    S=0,T=3201;
    for(int i=1;i<=1600;i++){
        insert(S,i*2-1,1);
        insert(i*2,T,1);
        for(int j=1;j<i;j++){
            int t=sqrt(j+i);
            if(t*t==j+i) insert(j*2-1,i*2,1);
        }
        m+=Dinic();
        if(i-m>n){
            printf("%d\n",i-1);break;
        } 
    }
    return 0;
}

 

线性规划做法

f(n)= (n*n-2)/2+n;//(n mod 2==0)

f(n)= (n*n-1)/2+n;//(n mod 2==1)

 

#include<cstdio>
using namespace std;
int n,ans;
int main(){
    freopen("balla.in","r",stdin);
    freopen("balla.out","w",stdout);
    scanf("%d",&n);
    if(n&1) ans=(n*n-1>>1)+n;
    else ans=(n*n-2>>1)+n;
    printf("%d",ans);
    return 0;
}

 

posted @ 2017-01-02 11:06  神犇(shenben)  阅读(311)  评论(0编辑  收藏  举报