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 }

 

posted @ 2019-01-01 17:21  Unstoppable728  阅读(193)  评论(0编辑  收藏  举报