zoukankan      html  css  js  c++  java
  • P2765 魔术球问题

    洛谷

    假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球。

    (1)每次只能在某根柱子的最上面放球。

    (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。

    试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可放11 个球。

    题解:

    • 先将其转化为一张图  并把能连的边都连上   数字小的连数字大的,因为从小到大放入
    • 可以将其转化为最小路径覆盖  每条路径就是每个石柱上的一串数字
    • 显然当最少路径大于石柱个数的时候  不能再放了
    • 不断更新二分图即可
    • 注意每次跑的是残量网络 所以累和即可
    #include<bits/stdc++.h>
    using namespace std;
    #define inf 0x3f3f3f3f
    const int N=1e5+10;
    const int M=1e5+10;
    struct Edge {
        int to, next, w;
    } edge[M<<1];
    int head[N],cur[N],pos=1,level[N];
    void add(int a, int b, int c) {
        edge[++pos] = (Edge){b, head[a], c};head[a] = pos;
        edge[++pos] = (Edge){a, head[b], 0};head[b] = pos;
    }
    bool bfs(int s, int t) {
        memset(level, 0, sizeof level);
        queue<int> q;
        level[s] = 1;
        q.push(s);
        while (!q.empty()) {
            int pos = q.front();q.pop();
            for (int i = head[pos]; i; i = edge[i].next) {
                int v = edge[i].to;
                if (!edge[i].w || level[v]) continue;
                level[v] = level[pos] + 1;
                q.push(v);
            }
        }
        return level[t];
    }
    int dfs(int s, int t, int flow) {
        if(s==t||flow==0)return flow;
        int f,ret = 0;
        for (int &i = cur[s],v; i; i = edge[i].next) {
             v = edge[i].to;
            if (level[v] == level[s] + 1 && (f=dfs(v,t,min(flow,edge[i].w)))>0) {
                edge[i].w -= f;
                edge[i ^ 1].w += f;
                flow -= f;
                ret += f;
                if(!flow)break;
            }
        }
        return ret;
    }
    int dinic(int s, int t) {
        int ret = 0;
        while (bfs(s, t)) memcpy(cur,head,sizeof cur),ret += dfs(s, t, inf);
        return ret;
    }
    int spr[N],s,t,n,vis2[N],to[N];
    int main() {
        cin>>n;s=0,t=N-1;int T=10000;
    
        for(int i=1;i<=10000;i++)spr[i]=i*i;
        int pos=1,sum=0;
        while(1) {
            add(s,pos,1);add(pos+T,t,1);
            int x=lower_bound(spr+1,spr+1+1000,pos)-spr;
            for(int j=2*x;j>=1;j--) {
                int temp=spr[j]-pos;
                if(temp>0&&temp<pos)add(temp,pos+T,1);
            }
            sum+=dinic(s,t);
            if(pos-sum>n)break;
            pos++;
        }
        pos--;
        cout<<pos<<endl;
        for(int i=1;i<=pos;i++)
            for(int j=head[i];j;j=edge[j].next) if(!edge[j].w&&edge[j].to!=s) {
                to[i]=edge[j].to-T;break;
            }
        for(int i=1;i<=pos;i++) {
            if(vis2[i])continue;
            for(int k=i;k;k=to[k])
                vis2[k]=1,printf("%d ",k);
            printf("
    ");
        }
    }
    View Code
  • 相关阅读:
    用例图会不会
    存储过程进阶(vb.net+SQL Server2008环境)
    众说纷纭,我也说“云”
    三层架构之抽象工厂加反射实现数据库转换
    三层架构之抽象工厂加反射&mdash;&mdash;实现数据库转换
    存储过程懂不懂
    8个对于Web设计和开发人员非常有用的在线工具
    TexturePacker的使用(图片打包再一起)
    cocos2dx游戏摇杆的实现方法
    cocos2dx 矩形碰撞检测
  • 原文地址:https://www.cnblogs.com/bxd123/p/11808587.html
Copyright © 2011-2022 走看看