• BZOJ1298:[SCOI2009]骰子的学问


    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
  • 相关阅读:
    APACHE 服务器开启URL REWRITE模块的方法
    tp路由+伪静态+去掉index.php
    PHP实现伪静态方法汇总
    在SAE分布式服务上开发需要解决的问题
    [置顶] 刘汝佳《训练指南》动态规划::Beginner (25题)解题报告汇总
    android 桌面小工具(Widget)开发教程
    VC++深入详解-第四章学习心得
    LED音乐频谱之输入数据处理
    CSharp设计模式读书笔记(15):命令模式(学习难度:★★★☆☆,使用频率:★★★★☆)
    CSharp设计模式读书笔记(14):职责链模式(学习难度:★★★☆☆,使用频率:★★☆☆☆)
  • 原文地址:https://www.cnblogs.com/GhostReach/p/6255679.html
Copyright © 2020-2023  润新知