ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Luogu P3681 [CERC2016]舞动的盘子 Dancing Disks

2020-07-21 21:33:08  阅读:292  来源: 互联网

标签:const Dancing int Luogu Disks tp push include define


法老讲课讲到的一道妙题,觉得很有趣就写了下

首先我们观察题意,发现原问题可以转化为一个排序问题

考虑我们求出\(f_{i,j}\)表示在\((i,j)\)格子上,最多可以保证顶上的\(f_{i,j}\)个数有序

考虑对于所有的\((i',j'),i'\in[1,i],j'\in[1,j],i'\not =i\or j'\not= j\),利用多路归并的思想,这上面的盘子都可以摆到\((i,j)\)上

换句话说就是\(f_{x,y}=\sum_{i=1}^x\sum_{j=1}^y f_{i,j} (i\not =x\or j\not= y)\)

然后\(f_{6,6}\)上就是最后能排好序的盘子数目了,我们打个表看看:

woc好像不行的亚子,难道就这样GG了?

我们再仔细想一下,其实对于\(f_{1,2}\)和\(f_{2,1}\),它们其实是可以通过讨论来做到\(f_{1,2}=f_{2,1}=2\)的,这样一来还是按照上面的式子我们算一算:

和数据范围完美契合,可以通过此题

然后稍微讲下实现吧,首先我们肯定是考虑递归完成这个问题,设一个函数solve(x,y,tp)表示做到\((x,y)\)且这个位置上要放成升序还是降序

至于为什么要升降序,因为考虑我们归并的时候由于每个格子相当于是一个,因此之前的格子的升降序就要与后面的相反

然后多路归并的话就直接用堆来维护即可,有一些小细节

总复杂度应该是\(O(6^6+36\times n\times \log 36)\)

#include<cstdio>
#include<utility>
#include<queue>
#include<stack>
#include<iostream>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef pair <int,int> pi;
typedef pair <int,pi> ipi;
const int N=10;
priority_queue <ipi,vector<ipi>,less<ipi> > big;
priority_queue <ipi,vector<ipi>,greater<ipi> > small;
stack <int> A[N][N],B[N][N]; int n,x;
inline void move(const pi& A,const pi& B) //move the top disk of A to B
{
	int x=A.fi; while (x<B.fi) printf("%d %d D 1\n",x++,A.se);
	int y=A.se; while (y<B.se) printf("%d %d R 1\n",x,y++);
}
inline void sort_greater(CI x,CI y)
{
	for (RI i=1,j;i<=x;++i) for (j=1;j<=y;++j)
	if ((i!=x||j!=y)&&!A[i][j].empty()) big.push(mp(A[i][j].top(),mp(i,j)));
	while (!big.empty())
	{
		pi nw=big.top().se; A[x][y].push(big.top().fi); big.pop(); move(nw,mp(x,y));
		if (A[nw.fi][nw.se].pop(),!A[nw.fi][nw.se].empty()) big.push(mp(A[nw.fi][nw.se].top(),nw));
	}
}
inline void sort_less(CI x,CI y)
{
	for (RI i=1,j;i<=x;++i) for (j=1;j<=y;++j)
	if ((i!=x||j!=y)&&!A[i][j].empty()) small.push(mp(A[i][j].top(),mp(i,j)));
	while (!small.empty())
	{
		pi nw=small.top().se; A[x][y].push(small.top().fi); small.pop(); move(nw,mp(x,y));
		if (A[nw.fi][nw.se].pop(),!A[nw.fi][nw.se].empty()) small.push(mp(A[nw.fi][nw.se].top(),nw));
	}
}
inline void solve(int x,int y,bool tp) // tp=0 less otherwise greater
{
	if (x==1&&y==1)
	{
		if (!B[x][y].empty()) A[x][y].push(B[x][y].top()),B[x][y].pop(); return;
	}
	if ((x==1&&y==2)||(x==2&&y==1))
	{
		if (B[1][1].empty()) return; int a=B[1][1].top(); B[1][1].pop();
		if (B[1][1].empty()) return A[x][y].push(a),move(mp(1,1),mp(x,y));
		int b=B[1][1].top(); B[1][1].pop();
		if ((a>b)^tp) printf("%d %d %c 2\n",1,1,x==1?'R':'D');
		else printf("%d %d %c 1\n%d %d %c 1\n",1,1,x==1?'R':'D',1,1,x==1?'R':'D');
		if (tp) A[x][y].push(max(a,b)),A[x][y].push(min(a,b));
		else A[x][y].push(min(a,b)),A[x][y].push(max(a,b)); return;
	}
	for (RI i=x,j;i;--i) for (j=y;j;--j) if (i!=x||j!=y) solve(i,j,tp^1);
	if (tp) sort_greater(x,y); else sort_less(x,y);
}
int main()
{
	scanf("%d",&n); for (RI i=1;i<=n;++i)
	scanf("%d",&x),B[1][1].push(x); return solve(6,6,1),0;
} 

标签:const,Dancing,int,Luogu,Disks,tp,push,include,define
来源: https://www.cnblogs.com/cjjsb/p/13357523.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有