LuoguP2765 魔术球问题(最大流)
题目描述
«问题描述:
假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球。
(1)每次只能在某根柱子的最上面放球。
(2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可放11 个球。
«编程任务:
对于给定的n,计算在n根柱子上最多能放多少个球。
输入输出格式
输入格式:
第1 行有1个正整数n,表示柱子数。
输出格式:
程序运行结束时,将n 根柱子上最多能放的球数以及相应的放置方案输出。文件的第一行是球数。接下来的n行,每行是一根柱子上的球的编号。
解题思路:
假如说告诉你多少球,需要多少柱子是显然可求的。
那和这道题就一样了。
发现球多柱子自然多,因为球只能一个一个摞,
所以没添加一个球只能放在没添加时的合法方案上的,
所以柱子数单增。
不要二分答案,那样还要拆图,枚举就好了。
注意要记录方案。
代码:
1 #include<cmath> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<algorithm> 6 const int oo=0x3f3f3f3f; 7 namespace stb{ 8 template<class tnt> 9 class queue{ 10 #define INF 1000000 11 public: 12 queue(){h=1,t=0;} 13 int nxt(int x){if(x+1==INF)return 1;return x+1;} 14 bool empty(void){return nxt(t)==h;} 15 void push(tnt x){t=nxt(t);l[t]=x;} 16 tnt front(void){return l[h];} 17 void clear(void){h=1;t=0;} 18 void pop(void){h=nxt(h);} 19 private: 20 tnt l[INF]; 21 int h,t; 22 #undef INF 23 }; 24 }; 25 struct pnt{ 26 int hd; 27 int lyr; 28 int nxt; 29 int now; 30 bool nos; 31 }p[100000]; 32 struct ent{ 33 int twd; 34 int lst; 35 int vls; 36 }e[1000000]; 37 int cnt; 38 int n,m; 39 int S,T; 40 int top; 41 stb::queue<int>Q; 42 std::vector<int>Ans[600]; 43 void ade(int f,int t,int v) 44 { 45 cnt++; 46 e[cnt].twd=t; 47 e[cnt].vls=v; 48 e[cnt].lst=p[f].hd; 49 p[f].hd=cnt; 50 return ; 51 } 52 bool Bfs(void) 53 { 54 Q.clear(); 55 for(int i=0;i<=(m<<1|1);i++) 56 p[i].lyr=0; 57 p[S].lyr=1; 58 Q.push(S); 59 while(!Q.empty()) 60 { 61 int x=Q.front(); 62 Q.pop(); 63 for(int i=p[x].hd;i;i=e[i].lst) 64 { 65 int to=e[i].twd; 66 if(p[to].lyr==0&&e[i].vls>0) 67 { 68 p[to].lyr=p[x].lyr+1; 69 if(to==T) 70 return true; 71 Q.push(to); 72 } 73 } 74 } 75 return false; 76 } 77 int Dfs(int x,int fll) 78 { 79 if(x==T) 80 return fll; 81 for(int& i=p[x].now;i;i=e[i].lst) 82 { 83 int to=e[i].twd; 84 if(p[to].lyr==p[x].lyr+1&&e[i].vls>0) 85 { 86 int ans=Dfs(to,std::min(fll,e[i].vls)); 87 if(ans>0) 88 { 89 e[i].vls-=ans; 90 e[((i-1)^1)+1].vls+=ans; 91 p[x].nxt=to; 92 if(S!=x) 93 p[to-1].nos=true; 94 return ans; 95 } 96 } 97 } 98 return 0; 99 } 100 int Dinic(void) 101 { 102 int ans=0; 103 while(Bfs()) 104 { 105 for(int i=0;i<=(m<<1|1);i++) 106 p[i].now=p[i].hd; 107 int dlt; 108 while(dlt=Dfs(S,oo)) 109 ans+=dlt; 110 } 111 return ans; 112 } 113 int main() 114 { 115 int bulp=0; 116 scanf("%d",&n); 117 S=0,T=1;m=1; 118 for(int i=1;;i++) 119 { 120 m++; 121 ade(S,i<<1,1); 122 ade(i<<1,S,0); 123 ade(i<<1|1,T,1); 124 ade(T,i<<1|1,0); 125 for(int j=sqrt(i);j*j-i<i;j++) 126 { 127 if(j*j-i<=0) 128 continue; 129 ade((j*j-i)<<1,i<<1|1,1); 130 ade(i<<1|1,(j*j-i)<<1,0); 131 } 132 bulp+=1-Dinic(); 133 if(bulp==n+1) 134 { 135 printf("%d\n",i-1); 136 break; 137 } 138 for(int j=1;j<=top;j++) 139 Ans[j].clear(); 140 top=0; 141 for(int j=1;j<=i;j++) 142 { 143 if(!p[j<<1].nos) 144 { 145 top++; 146 for(int k=j<<1;k!=S&&k>0;k=p[k].nxt-1) 147 Ans[top].push_back(k>>1); 148 } 149 } 150 } 151 for(int i=1;i<=top;i++) 152 { 153 for(int j=0;j<Ans[i].size();j++) 154 printf("%d ",Ans[i][j]); 155 printf("\n"); 156 } 157 return 0; 158 }