您的位置:首页 > 其它

【JZOJ 5284】 超级翻转

2017-08-16 22:29 197 查看

Description





1<=n<=15,1<=数据组数<=5

Analysis

这种题,发现数据范围暴力过不了,就应该发掘一下移动的性质

显然一条边走的次数可以简化成0/1

一个格子的状态取决于其相邻四条边走的次数异或

这样可以对每个格子列出方程,不过并不知道这个idea可不可做

继续发掘

如果一个点四周被绕了一圈,那么造成的影响仅是这个格子四周的格子反色

并且,由于我们可以从起点走到一个点绕一圈再原路反回来,所以走原路返回的时候经过的那些边相当于不计影响

这就是个很好的性质了,不论起点在哪,我们都可以任意选定格子,造成的贡献是四周的格子反色

这就有点像这题

不过也可能不绕圈啊!!!

这TM就GG没关系,我们枚举一个终点

那么起点到终点必定会有一条路径,这条路径是什么?

在路径上绕一个圈试试?

路径刚好进行了偏移,归纳一发,我们可以通过选择点绕圈来更改路径(感性)

那么暴力走一遍,暴力反色,就变成上面那个题了

然后应该就能过了,复杂度应该是n32n,实际跑得挺快

你以为这样就完了?

一个巨大的优化



选红勾的格子等价于选蓝勾的格子

我们不需要枚举第一行的状态

存在一种可行解,第一行全不选

复杂度变成n3

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,b,a) for(int i=b;i>=a;i--)
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define mset(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int N=20;
int n,xs,ys,xt,yt,a

,b

,c

;
//c:a matrix,value 1/0 standing node(i,j) is choosen or not
void go(int xs,int ys,int xt,int yt)
{
int fx=xs<xt?1:-1;
for(;xs!=xt;xs+=fx)
if(fx==1) b[xs][ys-1]^=1,b[xs][ys]^=1;
else b[xs-1][ys-1]^=1,b[xs-1][ys]^=1;
fx=ys<yt?1:-1;
for(;ys!=yt;ys+=fx)
if(fx==1) b[xs-1][ys]^=1,b[xs][ys]^=1;
else b[xs-1][ys-1]^=1,b[xs][ys-1]^=1;
fo(i,0,n+1) b[i][0]=b[0][i]=b[i][n+1]=b[n+1][i]=0;
}
void output(int xs,int ys,int xt,int yt,int p)
{
int fx;
if(!p)
{
fx=xs<xt?1:-1;
for(;xs!=xt;xs+=fx) putchar(fx==1?'D':'U');
fx=ys<yt?1:-1;
for(;ys!=yt;ys+=fx) putchar(fx==1?'R':'L');
}
else
{
fx=ys<yt?1:-1;
for(;ys!=yt;ys+=fx) putchar(fx==1?'R':'L');
fx=xs<xt?1:-1;
for(;xs!=xt;xs+=fx) putchar(fx==1?'D':'U');
}
}
int main()
{
freopen("turn.in","r",stdin);
freopen("turn.out","w",stdout);
int T;
for(scanf("%d",&T);T;T--)
{
scanf("%d",&n);
fo(i,1,n)
fo(j,1,n) scanf("%d",&a[i][j]);
scanf("%d %d",&xs,&ys);
bool p=0;
for(xt=1;xt<=n+1;xt++)
{
for(yt=1;yt<=n+1;yt++)
{
memcpy(b,a,sizeof(a));
go(xs,ys,xt,yt);
mset(c,0);
fo(i,2,n)//it can be proved that the first line of c can be all 0
fo(j,1,n)
c[i][j]=c[i-1][j-1]^c[i-2][j]^c[i-1][j+1]^b[i-1][j];
bool ok=1;
fo(i,1,n)
if(c
[i-1]^c[n-1][i]^c
[i+1]^b
[i]) {ok=0;break;}
if(!ok) continue;
p=1;break;
}
if(p) break;
}
if(!p) {puts("No Solution!");continue;}
fo(i,1,n)
fo(j,1,n)
if(c[i][j])
{
output(xs,ys,i,j,0);
printf("RDLU");
output(i,j,xs,ys,1);
}
output(xs,ys,xt,yt,0);printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: