• [洛谷1240]诸侯安置


    问题描述

        很久以前,有一个强大的帝国,它的国土呈正方形状(转45度看)。

        这个国家有若干诸侯。由于这些诸侯都曾立下赫赫战功,国王准备给他们每人一块封地(正方形中的一格)。但是,这些诸侯又非常好战,当两个诸侯位于同一行或同一列时,他们就会开战。如下图2-3为n=3时的国土,阴影部分表示诸侯所处的位置。前两幅图中的诸侯可以互相攻击,第三幅则不可以。

       

     国王自然不愿意看到他的诸侯们互相开战,致使国家动荡不安。因此,他希望通过合理的安排诸侯所处的位置,使他们两两之间都不能攻击。

       现在,给出正方形的边长n,以及需要封地的诸侯数量k,要求你求出所有可能的安置方案数。(n≤100,k≤2n2-2n+1)

       由于方案数可能很多,你只需要输出方案数除以504的余数即可。

    输入说明

        仅一行,两个整数n和k,中间用一空格隔开。

    输出说明

        一个整数,表示方案数除以504的余数。

    样例输入

        2 2

    样例输出

        4

    样例说明

        四种安置方案如图2-4所示。注意:镜面和旋转的情况属于不同的方案。

     

    思路

    首先可以证明这个图可以转换成如下的形式:

     然后我们会容易发现一种不同与搜索的动态规划做法.

    f[i,j]:=f[i,j]+f[k,j-1]*(Len[i]-(j-1)) [j-1<=k<=i-1]

    1.f[i,j]表示前i列放置j个的方案,且第j个放在第i列上,

    2.前面f[k,j-1]个都需要累加上来,举一个说明为什么需要累加:对于前4排放置2个的情况(平移后的),2个即可以放在第一列和第三列,也可以放在第一列和第四列,所以需要把这些分布在不同列的情况累加上来。

    3.乘(Len[i]-(j-1))是因为前面k列放了j-1个棋子了,然后每行只能放一个棋子,所以第j个棋子在第i列可以放的情况就是Len[i]-(j-1),len[i]是第i列有多少行,程序中是L[i]

    const mo=504;    
      
    var f:array[0..200,0..200]of int64;    
        l:array[0..2000]of longint;    
        n,k,i,j,kk,m:longint;    
        ans:int64=0;    
        
    function min(a,b:longint):longint;    
    begin    
       if a>b then exit(b) else exit(a);    
    end;    
        
    procedure change;    
    begin    
        m:=2*n-1;    
        if k>m then    
            begin    
                writeln(0);    
                halt;    
            end;    
        if k=0 then    
            begin    
                writeln(1);    
                halt;    
            end;    
    end;    
        
    begin    
        fillchar(f,sizeof(f),0);    
        readln(n,k);    
        change;    
        for i:=1 to m do    
            if odd(i) then l[i]:=i else l[i]:=i-1;    
        for i:=1 to m do    
            begin    
                f[i,1]:=l[i];    
                for j:=2 to min(i-1,k) do    
                    for kk:=j-1 to i-1 do    
                        f[i,j]:=(f[i,j]+f[kk,j-1]*(l[i]-j+1))mod mo;    
            end;    
        ans:=0;    
        if k=1 then    
            begin    
                writeln((n shl 1)*(n-1)+1);    
                halt;    
            end;    
         for i:=k to m do ans:=(ans+f[i,k]) mod mo;    
         writeln(ans mod mo);    
    end. 
    View Code
  • 相关阅读:
    How does Android, PHP, SQL, JSON, and Remote Databases work together?
    Gson Json
    Protocol Android
    AsyncTask、多线程及线程通信
    线程-Android
    HTTP请求-Android
    Make Your First Android App
    Git版本控制软件结合GitHub从入门到精通常用命令学习手册
    正向代理设置
    vscode 调试 react 项目
  • 原文地址:https://www.cnblogs.com/yangqingli/p/4930510.html
Copyright © 2020-2023  润新知