BZOJ1298骰子的学问

Posted G . H . O . S . T . R . E . A

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1298骰子的学问相关的知识,希望对你有一定的参考价值。

Description

Input

第一行为两个整数n, m。第二行有n个整数,为a1,a2, …, an。

Output

包含n行,每行m个1~n×m的正整数,各不相同,以空格分开。如果有多解,输出任意一组解;如果无解,输出一个整数0。

Sample Input & Sample Output

 

HINT

30%的数据满足n, m≤10

100%的数据满足3≤n, m≤200

 

题解:

把ai认为是i的父亲,使其连边,那么题目给出的关系构成了一个基环树森林。

对于在环外、指向环的边(即“树”的部分),使骰子的每一个面都比其父亲大。

观察1、4样例可以发现一个构造方式:对于一个大小为n环,从第一个点开始,逆着父亲边放入1~n;再从第一个点在环上的儿子开始,逆着父亲边以此放入n+1~2*n,直到放满n*m个数。

但是这个构造法在样例3中失败了。事实上,可以证明,只有在像样例3这种环大小为3骰子面数为4的情况下,该方法会失效。对于这种情况,进行特判。

注意环大小为2或是m<=2的情况,一定无法构造。

 

代码:

 1 const
 2   bb:array[1..12]of longint=(1,2,4,3,7,5,10,8,6,11,9,12);
 3 var
 4   i,j,k,l,n,m,cnt:longint;
 5   fa,a,b,c:array[0..1001]of longint;
 6   d:array[0..1001,0..1001]of longint;
 7 procedure ss2(x:longint);
 8 var i:longint;
 9 begin
10   if a[x]<2 then
11   begin
12     for i:=1 to m do
13     begin inc(cnt); d[x,i]:=cnt; end;
14     a[x]:=2;
15   end;
16   i:=c[x];
17   while i>0 do
18   begin
19     if a[i]<2 then ss2(i);
20     i:=b[i];
21   end;
22 end;
23 procedure ss(x:longint);
24 var i,j,k,l,xx:longint;
25 begin
26   a[x]:=1; x:=fa[x];
27   while a[x]=0 do
28   begin
29     a[x]:=1; x:=fa[x];
30   end;
31   k:=1; xx:=fa[x]; a[x]:=2;
32   while x<>xx do begin inc(k); a[xx]:=2; xx:=fa[xx]; end;
33   if k<=2 then begin writeln(0); halt; end;
34   if(k=3)and(m=4)then
35   begin
36     for i:=1 to 12 do
37     begin
38       d[x,1+((i-1)div 3)]:=bb[i];
39       x:=fa[x];
40     end;
41   end else
42   begin
43     for i:=1 to m do
44     begin
45       l:=cnt+k;
46       for j:=1 to k do
47       begin
48         d[x,i]:=l; dec(l);
49         if j<>k then x:=fa[x];
50       end;
51       cnt:=cnt+k;
52     end;
53   end;
54   for i:=1 to k do
55   begin
56     ss2(x); x:=fa[x];
57   end;
58 end;
59 begin
60   readln(n,m);
61   for i:=1 to n do
62   begin
63     read(fa[i]);
64     b[i]:=c[fa[i]]; c[fa[i]]:=i;
65   end;
66   for i:=1 to n do
67   if a[i]=0 then ss(i);
68   for i:=1 to n do
69   begin
70     for j:=1 to m do write(d[i,j],\' \');
71     writeln;
72   end;
73 end.
View Code

以上是关于BZOJ1298骰子的学问的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1298:[SCOI2009]最长距离

bzoj 4603 平凡的骰子

[BZOJ1599] [Usaco2008 Oct] 笨重的石子

Bzoj2339--Hnoi2011卡农

BZOJ-2653middle 可持久化线段树 + 二分

编程算法 - n个骰子的点数(递归) 代码(C)