[网络流24题]魔术球问题(简化版
来源:互联网 发布:终极算法 pdf 编辑:程序博客网 时间:2024/06/01 16:27
问题描述: 假设有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
每一行表示一个柱子上的球
在上一次的残余网络建新边-》(由于从[1~...]按顺序+反向边)-》得新的流
就是编号较小的顶点向编号较大的顶点连接边(皆可),条件是两个球可以相邻,即编号之和为完全平方数。每根柱子看做一条路径,N根柱子要覆盖掉所有点,一个解就是一个路径覆盖。
最小路径覆盖数随球的数量递增不递减,满足单调性,所以可以枚举答案(或二分答案),对于特定的答案求出最小路径覆盖数,一个可行解就是最小路径覆盖数等于N的答案,求出最大的可行解就是最优解。本问题更适合枚举答案而不是二分答案,因为如果顺序枚举答案,每次只需要在残量网络上增加新的节点和边,再增广一次即可。如果二分答案,就需要每次重新建图,大大增加了时间复杂度。
#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<queue>#include<map>#include<cstdlib>#include<algorithm>#define V 10605#define mod 1000000007#define LL long longusing namespace std;int n,m,T,S;int ls[V],pre[V],dep[V],q[V];struct da{ int to,next,dis; }Edge[V*15];int head[V],tot,ans,s;inline void add(int x,int y,int zz){ Edge[tot].to=y; Edge[tot].dis=zz; Edge[tot].next=head[x]; head[x]=tot++; Edge[tot].to=x; Edge[tot].dis=0; Edge[tot].next=head[y]; head[y]=tot++; }bool Bfs() { // bfs建立层次图 memset(dep, 0, sizeof(dep)); int hd,tl; hd = tl = 0; q[++ tl] = S, dep[S] = 1; while(hd<tl) { int op = q[++hd]; for(int i = head[op] ; i != -1 ; i = Edge[i].next) { if(Edge[i].dis&&(!dep[Edge[i].to])) { dep[Edge[i].to] = dep[op]+1; q[++ tl] = Edge[i].to; if(Edge[i].to==T) return true; } // 遍历到T就返回,此时该层次图已建好 } // 再访问其它的点没有必要 } return false;}int Dfs(int op, int fw) { if(op==T) return fw; int tmp =fw,k; for(int i = head[op] ; i != -1 ; i = Edge[i].next) { if(Edge[i].dis&&tmp&&dep[Edge[i].to]==dep[op]+1) { k = Dfs(Edge[i].to, min(Edge[i].dis, tmp)); if(!k) { //该点后面没有路径,所以要从层次图中删去 dep[Edge[i].to] = 0; // 因为和当前点op层次相同的点 continue; // 还可能会访问到它 } Edge[i].dis-= k, Edge[i^1].dis+= k,tmp-= k; } } return fw-tmp;}int solve(){ int i,flow=0; while(Bfs()) { ans-=Dfs(S,mod); } return flow;}inline void init(){ tot=0; memset(head,-1,sizeof(head)); } int vis[V];inline int haha(){ // freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout); freopen("balla.in","r",stdin); freopen("balla.out","w",stdout); memset(head,-1,sizeof(head)); cin>>n; T=2*1600+10; while(ans<=n) { ans++;s++; for(int i=1;i<s;i++) if(sqrt(i+s)==(int)sqrt(i+s)) add(s,i+1600,1); add(0,s,1);add(s+1600,T,1); solve(); } //return 0; printf("%d",s-1);//while(1); return 0; /*int sd=s-1,x; while(1) { for(int i=s-1;i>=1;i--) { cout<<i<<endl; if(!vis[i]) { vis[i]=1; for(int j=head[i];j!=-1;j=Edge[j].next) { if(!Edge[j].dis) { //x=1; sd--; ls[Edge[j].to]=i; i=Edge[j].to+1; break; } } } } if(sd==1)break; //cout<<" ER"<<endl; } */ return 0;}int gg=haha();int main(){;}
阅读全文
0 0
- [网络流24题]魔术球问题(简化版)
- cogs396 [网络流24题]魔术球问题简化版
- [网络流24题]魔术球问题(简化版
- 396. [网络流24题]魔术球问题(简化版)(网络流+二分答案)
- [网络流24题][COGS396]魔术球问题简化版(最小割)
- cogs 396. [网络流24题]魔术球问题(简化版
- [网络流24题]魔术球问题(简化版) 最小路径覆盖+二分答案 + 很快的最大流
- 【网络流24题】魔术球问题
- 【网络流24题】魔术球问题
- 【网络流24题】魔术球问题
- [网络流24题]魔术球问题
- cogs 魔术球问题(简化版)
- 魔术球问题(网络24题,三)
- 线性规划与网络流24题 04魔术球问题
- 网络流与线性规划24题04魔术球问题
- [网络流24题 #4]魔术球问题
- kyeremal-网络流24题T4-魔术球问题
- 魔术球问题[网络流24题之4]
- 框架学习之spring整合hibernate、struts2框架-01基础配置
- SQL 使用update case when 批量更新
- 多重背包的二进制优化
- LR入门
- BZOJ1179: [Apio2009]Atm
- [网络流24题]魔术球问题(简化版
- Visual Studio运行自定义外部工具
- [Oracle] sqlplus / as sysdba ora-01031 insufficient privileges
- 小米笔记本在Kali Linux下所遇问题部分解决方案(持续更新中)
- 学习发布/订阅机制
- 实现listview的item侧滑功能
- FOJ2277(dfs序 + 树状数组区间更新)
- 笔记3 《C++大学教程》
- 曝光与测光