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


    问题描述: 
    假设有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

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

    这应该是有spj的

    虽然是 网络流 但是贪心也能过

    详解在 dinic中

     1 /*
     2     尽管是网络流24题之一 
     3     我还是忍不住用了贪心 
     4 */
     5 #include <cmath>
     6 #include <ctype.h>
     7 #include <cstdio>
     8 
     9 const int MAXN=1010;
    10 
    11 int tot,n;
    12 
    13 int a[MAXN][MAXN];
    14 
    15 inline void read(int&x) {
    16     register char c=getchar();
    17     for(x=0;!isdigit(c);c=getchar());
    18     for(;isdigit(c);x=x*10+c-48,c=getchar());
    19 }
    20 
    21 inline bool check(int x) {
    22     int p=sqrt(x);
    23     if(p*p==x) return true;
    24     else return false;
    25 }
    26 
    27 int hh() {
    28     freopen("balla.in","r",stdin);
    29     freopen("balla.out","w",stdout);
    30     read(n);
    31     int it=1;
    32     a[++tot][++a[tot][0]]=1;
    33     while(true) {
    34         int flag=0;++it;
    35         for(int i=1;i<=tot;++i) {
    36             int t=it+a[i][a[i][0]];
    37             if(check(t)) a[i][++a[i][0]]=it,flag=1;
    38             if(flag) break;
    39         }
    40         if(flag) continue;
    41         tot++;
    42         a[tot][++a[tot][0]]=it;
    43         if(tot>n) break;
    44     }
    45     printf("%d
    ",it-1);
    46 /*    for(int i=1;i<tot;++i) {
    47         for(int j=1;j<=a[i][0];++j)
    48           printf("%d ",a[i][j]);
    49         printf("
    ");
    50     }*/
    51     return 0;
    52 } 
    53 
    54 int sb=hh();
    55 int main() {;}
    贪心
     1 /*
     2     二分图匹配 
     3 */
     4 #include <cstdio>
     5 #include <cstring> 
     6 
     7 const int MAXN=4001;
     8 const int MAXM=30010;
     9 
    10 int n,mark[MAXM],vist[MAXM];
    11 
    12 bool c[MAXN],vis[MAXN];
    13 
    14 struct PLU {
    15     int to;
    16     int next;
    17 };
    18 PLU t[MAXM];
    19 
    20 int head[MAXN],tot=1;
    21 
    22 inline void add(int x,int y) {
    23     t[++tot].to=y;
    24     t[tot].next=head[x];
    25     head[x]=tot; 
    26 } 
    27 
    28 bool find(int x) {
    29     for(int i=head[x];i!=-1;i=t[i].next) {
    30         int to=t[i].to;
    31         if(!vis[to]) {
    32             vis[to]=true;
    33             if(!mark[to]||find(mark[to])) {
    34                 vist[x]=to,mark[to]=x;
    35                 return true;
    36             }
    37         } 
    38     }
    39     return false;
    40 }
    41 
    42 int hh() {
    43     freopen("balla.in","r",stdin);
    44     freopen("balla.out","w",stdout);
    45     int ans=0;
    46     scanf("%d",&n);
    47     memset(head,-1,sizeof head);
    48     for(int i=1;i<=63;++i) c[i*i]=true;
    49     for(int i=1;i<=1600;++i) {
    50         for(int j=1;j<i;++j)
    51             if(c[i+j]) add(i,j);
    52         for(int j=1;j<=i;++j) {
    53             if(!vist[j]) {
    54                 memset(vis,false,sizeof vis);
    55                 if(find(j)) ++ans;
    56             } 
    57         }
    58         if(i-ans>n) {
    59             printf("%d
    ",i-1);
    60             goto END; 
    61         } 
    62     }
    63 END:
    64     return 0;
    65 }
    66 
    67 int sb=hh();
    68 int main() {;}
    匈牙利算法
      1 /*
      2     对于每一个 x+y=i^2(x<y)
      3     依照题意我们知道 x,y 都能且只能使用一次
      4     所以我们可以把每一个数字 x 拆成 x1 和 x0
      5     其中 x1 加上一个比 x1 小的数字构成一个完全平方数
      6     x0 加上一个比 x0 大的数构成一个完全平方数
      7     再把所有的 (y0,z1)(y0+z1=i^2,y0<z1,i∈N+) 
      8     之间连一条有向边就是一个二分图匹配的问题了
      9     
     10     新增一个源 S 和汇 T 
     11     把当前的整数 x 拆成 x0 和 x1 
     12     连接一条容量为 1   从 S 到 x0 的有向边 
     13     连接一条容量为 1   从 x1 到 T 的有向边 
     14      连接一条容量为 1   从 x0 到 k(x0+k=i^2,k∈N+,i∈N+) 的有向边
     15 */
     16 #include <queue>
     17 #include <cmath>
     18 #include <cstring>
     19 #include <cstdio>
     20 
     21 const int MAXN=40010;
     22 const int INF=0x7fffffff;
     23 
     24 struct data {
     25     int to;
     26     int next;
     27     int val;
     28 }; 
     29 data e[MAXN];
     30 
     31 int head[MAXN],cur[MAXN],tot=1;
     32 
     33 int depth[MAXN];
     34 
     35 int src,decc,n;
     36 
     37 std::queue<int>q;
     38 
     39 inline void add(int x,int y,int z) {
     40     e[++tot].to=y;
     41     e[tot].val=z;
     42     e[tot].next=head[x];
     43     head[x]=tot;
     44 }
     45 
     46 inline int min(int a,int b) {
     47     return a<b?a:b;
     48 } 
     49 
     50 bool bfs() {
     51     for(int i=0;i<=decc;++i) cur[i]=head[i],depth[i]=-1;
     52     while(!q.empty()) q.pop();
     53     q.push(src);
     54     depth[src]=0;
     55     while(!q.empty()) {
     56         int u=q.front(); 
     57         q.pop();
     58         for(int i=head[u];i!=-1;i=e[i].next) {
     59             int to=e[i].to;
     60             if(e[i].val&&depth[to]==-1) {
     61                 depth[to]=depth[u]+1;
     62                 q.push(to);
     63                 if(to==decc) return true;
     64             }
     65         }
     66     }
     67     return false;
     68 }
     69 
     70 int dfs(int now,int flow) {
     71     if(now==decc) return flow;
     72     int used=0,delat;
     73     for(int & i=cur[now];i!=-1;i=e[i].next) {
     74         int to=e[i].to;
     75         if(e[i].val&&depth[to]==depth[now]+1) {
     76             delat=flow-used;
     77             delat=dfs(to,min(delat,e[i].val));
     78             e[i].val-=delat;
     79             e[i^1].val+=delat;
     80             used+=delat;
     81             if(used==flow) break; 
     82         }
     83     }
     84     if(!used) depth[now]=-1;
     85     return used;
     86 }
     87 
     88 int hh() {
     89     freopen("balla.in","r",stdin);
     90     freopen("balla.out","w",stdout);
     91     int ans=0,it=0;
     92     memset(head,-1,sizeof head);
     93     decc=1610*2;
     94     scanf("%d",&n);
     95     while(true) {
     96         ++ans,++it;
     97         for(int i=1;i<it;++i)
     98           if(sqrt(i+it)==int(sqrt(i+it))) 
     99             add(i,it+1600,1),add(it+1600,i,0);
    100         add(src,it,1);add(it,src,0);
    101         add(it+1601,decc,1);add(decc,it+1601,0);
    102         while(bfs())
    103           ans-=dfs(src,INF);
    104         if(ans>n) break;
    105     }
    106     printf("%d
    ",it-1);
    107     return 0;
    108 }
    109 
    110 int sb=hh();
    111 int main() {;}
    dinic


    作者:乌鸦坐飞机
    出处:http://www.cnblogs.com/whistle13326/
    新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

     
  • 相关阅读:
    【BZOJ1006】神奇的国度(弦图)
    弦图
    【BZOJ2946】公共串(后缀数组)
    【POJ1743】Musical Theme(后缀数组)
    JAVA和Tomcat运维整理
    linux shell 之if-------用if做判断
    Linux curl命令详解
    Intel HEX文件解析
    Linux bridge-utils tunctl 使用
    怎样查询锁表的SQL
  • 原文地址:https://www.cnblogs.com/whistle13326/p/7351469.html
Copyright © 2020-2023  润新知