[네트워크 흐름 24 문제] 마술 공 문제.
n 개의 기둥 이 있다 고 가정 하면 다음 과 같은 규칙 에 따라 이 n 개의 기둥 에 번호 가 1, 2, 3 인 공 을 순서대로 넣 어야 한다.
(1) 매번 어떤 기둥 의 맨 위 에 만 공 을 놓 을 수 있다.
(2) 같은 기둥 에서 두 개의 인접 구 의 번호 의 합 은 완전 제곱 수 이다.
n 개의 기둥 에 최대 몇 개의 공 을 넣 을 수 있 는 지 계산 하 는 알고리즘 을 시험 적 으로 설계 하 다.예 를 들 어 기둥 4 개 에 최대 11 개의 공 을 넣 을 수 있다.
주어진 n 에 대해 n 개의 기둥 에 최대 몇 개의 공 을 넣 을 수 있 는 지 계산 합 니 다.
Input
파일 의 첫 줄 에 1 개의 정수 n 이 있 는데 기둥 수 를 나타 낸다.
Output
프로그램 이 실 행 될 때 n 개의 기둥 에 가장 많이 놓 을 수 있 는 공 수 와 해당 하 는 배치 방안 을 출력 합 니 다.파일 의 첫 줄 은 공 수 입 니 다.다음 n 줄 은 줄 마다 기둥 위의 공의 번호 입 니 다.
Sample Input
4
Sample Output
11
1 8
2 7 9
3 6 10
4 5 11
HINT
n<60
해제
네트워크 흐름 의 최대 흐름 매 거 진 답 s. 그림 에서 노드 1, 2,....................................................................매번 최대 흐름 a 를 한 번 구 합 니 다. 만약 a - 1 = n 이 라면 s - 1 은 바로 답 입 니 다.
code
#include
#include
#include
#include
#include
#include
#include
#define N 10010
#define inf 0x7fffffff
using namespace std;
struct node
{
int next,to,s;
};
node Edge[N*20];
const int m=5000;
const int T=10000;
int n,ans,s,tot=1;
int head[N];
int h[N],que[N];
bool used[N];
int to[N];
void add(int x,int y,int z)
{
Edge[++tot].next=head[x];
Edge[tot].to=y;
Edge[tot].s=z;
head[x]=tot;
}
void ins(int x,int y)
{
add(x,y,1),add(y,x,0);
}
bool bfs()
{
queue<int>Q;
memset(h,-1,sizeof(h));
h[0]=0;
Q.push(0);
while(!Q.empty())
{
int now=Q.front();
Q.pop();
for(int i=head[now];i;i=Edge[i].next)
{
if(h[Edge[i].to]==-1&&Edge[i].s)
{
h[Edge[i].to]=h[now]+1;
Q.push(Edge[i].to);
}
}
}
if(h[T]==-1)return false;
return true;
}
int dfs(int u,int f)
{
if(u==T)return f;
int used=0;
for(int i=head[u];i;i=Edge[i].next)
{
if(!Edge[i].s||h[Edge[i].to]!=h[u]+1)continue;
int w=f-used;
w=dfs(Edge[i].to,min(w,Edge[i].s));
Edge[i].s-=w;
Edge[i^1].s+=w;
used+=w;
if(used==f)return f;
}
if(!used)h[u]=-1;
return used;
}
void dinic()
{
while(bfs())
ans-=dfs(0,inf);
}
void getans()
{
for(int i=1;ifor(int j=head[i];j;j=Edge[j].next)
{
if(Edge[j].s)continue;
to[i]=Edge[j].to-m;
break;
}
}
for(int i=1;iif(used[i])continue;
int t=i;
while(t!=-m)
{
printf("%d ",t);
used[t]=true;
t=to[t];
}
puts("");
}
}
int main()
{
cin>>n;
for(;;)
{
ans++,s++;
for(int i=1;iif(sqrt(i+s)==(int)sqrt(i+s))
ins(i,s+m);
ins(0,s),ins(s+m,T);
dinic();
if(ans>n)break;
}
printf("%d
",s-1);
getans();
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[네트워크 흐름 24 문제] 마술 공 문제.n 개의 기둥 이 있다 고 가정 하면 다음 과 같은 규칙 에 따라 이 n 개의 기둥 에 번호 가 1, 2, 3 인 공 을 순서대로 넣 어야 한다. (1) 매번 어떤 기둥 의 맨 위 에 만 공 을 놓 을 수 있다. (...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.