贪心做法

每次尽可能选择已经放过球的柱子

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int num[100][1000],n;
bool chk(const int &a,const int &b){
int t=sqrt(a+b);
return t*t==a+b;
}
int main(){
cin>>n;
int cnt=0;
while(++cnt){
bool f=0;
for(int i=1;i<=n;i++){
if(num[i][0]&&chk(num[i][num[i][0]],cnt)) num[i][++num[i][0]]=cnt,f=1;
if(f) break;
}
for(int i=1;i<=n;i++){
if(!num[i][0]) num[i][++num[i][0]]=cnt,f=1;
if(f) break;
}
if(!f) break;
}
printf("%d\n",cnt-1);
for(int i=1;i<=n;i++){
for(int j=1;j<=num[i][0];j++){
printf("%d ",num[i][j]);
}
printf("\n");
}
return 0;
}

网络流做法

我们可以将其转化成最小路径覆盖问题来做,

从小到大枚举答案,对于每一个新加进去的答案,寻找在已加进去的点中,满足题意的点,连一条边.

我们发现连好以后这是一个DAG图,其最小路径覆盖就是需要的最少柱子数,我们要找到一个最小路径覆盖<=n的最大解,即最后的答案

求最小路径覆盖可以用二分图做

这里有几个优化,具体见代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
int init(){
int rv=0,fh=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
rv=(rv<<1)+(rv<<3)+c-'0';
c=getchar();
}
return fh*rv;
}
const int MAXN=5000,MAXM=50005;
int head[MAXN],n,cur[MAXN],dep[MAXN],nume,s,t,maxflow;
queue<int> q;
bool f[MAXN];
struct edge{
int to,nxt,cap,flow;
}e[MAXM<<1];
void adde(int from,int to,int cap){
e[++nume].to=to;
e[nume].nxt=head[from];
head[from]=nume;
e[nume].cap=cap;
}
bool chk(const int &a,const int &b){
int t=sqrt(a+b);
return t*t==a+b;
}
bool bfs(){
memset(dep,0,sizeof(dep));
while(!q.empty()) q.pop();
q.push(s);dep[s]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!dep[v]&&e[i].flow<e[i].cap){
dep[v]=dep[u]+1;
if(v==t) return 1;//搜到汇点就结束,因为最新加进来的点一定在最前面,所以,搜到的这条路径就是新加进来的路径
q.push(v);
}
}
}
return 0;
}
int dfs(int u,int flow){
if(u==t) return flow;
int tot=0;
for(int &i=cur[u];i&&tot<flow;i=e[i].nxt){
int v=e[i].to;
if(dep[v]==dep[u]+1&&e[i].flow<e[i].cap){
if(int t=dfs(v,min(flow-tot,e[i].cap-e[i].flow))){
e[i].flow+=t;
e[((i-1)^1)+1].flow-=t;
tot+=t;
}
}
}
return tot;
}
void dinic(){
while(bfs()){
for(int i=s;i<=t;i++) cur[i]=head[i];
maxflow+=dfs(s,0x3f3f3f3f);
}
}
void print(int u){
printf("%d ",u);
f[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to-2000;
if(!f[v]&&e[i].flow){
print(v);
return;
}
}
}
int main(){
n=init();
s=0,t=4950;
int cnt=0;
while(++cnt){
adde(s,cnt,1);adde(cnt,s,0);
adde(cnt+2000,t,1);adde(t,cnt+2000,0);
for(int i=1;i<cnt;i++){
if(chk(i,cnt)){
adde(i,cnt+2000,1);
adde(cnt+2000,i,0);
}
}
dinic();
if(cnt-maxflow>n) break;
}
printf("%d\n",cnt-1); for(int k=1;k<=n;k++){
for(int i=1;i<cnt;i++) if(!f[i]){
print(i);break;
}
printf("\n");
}
return 0;
}

洛谷 [P2765] 魔术球问题的更多相关文章

  1. 洛谷 P2765 魔术球问题 解题报告

    P2765 魔术球问题 题目描述 问题描述: 假设有\(n\)根柱子,现要按下述规则在这\(n\)根柱子中依次放入编号为\(1,2,3,\dots\)的球. \((1)\) 每次只能在某根柱子的最上面 ...

  2. 洛谷 P2765 魔术球问题 (dinic求最大流,最小边覆盖)

    P2765 魔术球问题 题目描述 «问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2 ...

  3. 洛谷P2765魔术球问题 最小路径覆盖

    https://www.luogu.org/problemnew/show/P2765 看到这一题第一眼想到:这不是二分最大流吗,后来发现还有一种更快的方法. 首先如果知道要放多少个球求最少的柱子,很 ...

  4. 洛谷P2765 魔术球问题(最大流)

    传送门 %%%KSkun大佬 话说明明是网络流……这题竟然还有打表找规律和纯贪心AC的……都是神犇啊…… 来说一下如何建图.首先把每一个点拆成$X_i$和$Y_i$,然后$S$向$X_i$连一条容量为 ...

  5. 洛谷P2765 魔术球问题(贪心 最大流)

    题意 已经很简洁了吧. 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全 ...

  6. 洛谷P2765 魔术球问题

    题目链接:https://www.luogu.org/problemnew/show/P2765 知识点: 最大流 解题思路: 本题所有边的容量均为 \(1\). 从 \(1\) 开始加入数字,将这个 ...

  7. P2765 魔术球问题

    P2765 魔术球问题 贪心模拟就可以过.........好像和dinic没啥关系   找找规律发现可以贪心放.n又灰常小. 设答案=m 你可以$O(mn)$直接模拟过去 闲的慌得话可以像我用个$se ...

  8. P2765 魔术球问题 网络流二十四题重温

    P2765 魔术球问题 知识点::最小点覆盖 这个题目要拆点,这个不是因为每一个球只能用一次,而是因为我们要求最小点覆盖,所以要拆点来写. 思路: 首先拆点,然后就是开始建边,因为建边的条件是要求他们 ...

  9. [洛谷P2113] 看球泡妹子

    洛谷题目链接:看球泡妹子 题目背景 2014年巴西世界杯开幕了,现在满城皆是世界杯,商家们利用它大赚一笔,小明和小红也借此机会增进感情. 题目描述 本届世界杯共有N支球队,M场比赛.男球迷小明喜欢看比 ...

随机推荐

  1. ZOJ 1002 DFS

    Fire Net Time Limit: 2 Seconds      Memory Limit: 65536 KB Suppose that we have a square city with s ...

  2. Linux系统调优权威指南

    1.关闭SELINUX功能1.1 修改配置文件,使关闭SELINUX永久生效sed 's#SELINUX=enforcing#SELINUX=disables#g' /etc/selinux/conf ...

  3. SSH中后台传到前台一个信息集合,tr td中怎么进行排列,类似在一个div里排列书籍

    总觉得描述问题不对,这里详细说一下,就是把下面图片变成排列整齐,一行四个,多出来的两个排到下一行. 我问过群里的,给的答案都有些简介:1:后台排好了,前台循环出来: 2:前台直接循环,多出来的加< ...

  4. 如何让低版本IE浏览器支持HTML5标签并为其设置样式

    现代的浏览器都支持HTML5,HTML5定义了 8 个新的 HTML 语义元素.所有这些元素都是 块级 元素. 为了能让旧版本的浏览器正确显示这些元素,你可以设置 CSS 的 display 属性值为 ...

  5. js动态添加-表格逐行添加、删除、遍历取值

    关于js对表格进行逐行添加,今天抽空整理了一下:新建一个html文件(没有编辑器的可以新建一个demo.txt文件,然后改后缀名为demo.html),把下面代码全部贴进去即可.功能包括:表格添加一行 ...

  6. MLlib--FPGrowth算法

    转载请标明出处http://www.cnblogs.com/haozhengfei/p/c9f211ee76528cffc4b6d741a55ac243.html FPGrowth算法_挖掘商品之间的 ...

  7. ADO.NET复习总结(2)--连接池

    1. 2. 3.示例:在一百次循环中,执行数据库连接的打开和关闭,使用stopwatch查看所用的时间. using System; using System.Collections.Generic; ...

  8. JS中获取session中传过来的值对象

    摘录自:http://www.360doc.com/content/11/0316/13/5790498_101627263.shtml 把某一对象置于session范围内,并在JSP页面中提取ses ...

  9. Freemarker 入门示例

    初步学习freemarker ,先做一个简单的HelloWord程序! 新建一个WEB工程,下载(我使用的是freemarker-2.3.20)freemarker并导入freemarker.jar, ...

  10. python_鸡兔同笼问题

    鸡兔同笼问题 -- 今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何? --鸡和兔在一个笼子里,从上面数,有35个头:从下面数,有94只脚.问笼中各有几只鸡和兔 如何逻辑整理? -- 鸡头和兔子 ...