诸侯安置DP做法

来源:互联网 发布:华硕风扇控制软件 编辑:程序博客网 时间:2024/04/27 15:18

这几天考试,在考试中有这样一道题叫“诸侯安置”没过,但事后改对了。


题目:

诸侯安置
【问题描述】
很久以前,有一个强大的帝国,它的国土成正方形状,如图1 所示


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


国王自然不愿意看到他的诸侯们互相开战,致使国家动荡不安。因此,他希望通过
合理的安排诸侯所处的位置,使他们两两之同都不能攻击。
现在,给出正方形的边长n,以及需要封地的诸侯数量k,要求你求出所有可能的安置
方案数。(n≤100,k≤2n2-2n+1)
由于方案数可能很多,你只需要输出方案数除以504 的余数即可。
【输入】
仅一行,两个整数n 和k,中阍用一空格隔开。
【输出】
一个整数,表示方案数除以504 的余数。
【样例】
empire.in empire.out
2 2 4


本题我们先写DP做法,我们可以设置一个dp数组,让他的第一维来表示到第几列了,第二维表示能放几个诸侯。我们使列每次从左向右加一,由此得到每一列前最多能放多少个诸侯。而列的总数是n*2-1。在这要特别提醒大家,当i为奇数是最多有i种情况,可当i为偶数时却只有i-1种情况。 


#include<iostream>#include<cstdio>using namespace std;int n,Empire,ans = 0;int territory[250][250],q[250];int p;void init(){scanf("%d%d",&n,&Empire);if(Empire==0) { printf("1\n");exit(0);}      if(Empire>=2*n-1) { printf("0\n");  exit(0);}  p = n*2-1;//最多能有多少列 for(int i = 1;i <= p; i++){if(i%2){territory[i][1] = i;//当i为奇数时在第i列只放一个的话,会有i种情况 }else{territory[i][1] = i-1;//当i为偶数时在第i列只放一个的话,只有i-1种情况 }}}void work(){for(int i = 1;i <= 2*n-1; i++){ for(int j = 2;j <= i; j++){for(int k = 1;k <= i-j+1; k++){territory[i][j] += territory[i-k][j-1]*(i-j+i%2);//把在第i列放j个的所有情况累加起来 (转移式方程) territory[i][j] %= 504; //每次mod504 }}}for(int i = Empire;i < 2*n-1; i++){territory[2*n-1][Empire] += territory[i][Empire];//把所有能放 Empire个的情况数累加起来得到答案 territory[2*n-1][Empire] %= 504;}}int main(){freopen("Empire.in","r",stdin);freopen("Empire.out","w",stdout);init();work();printf("%d",territory[2*n-1][Empire]);return 0;}


0 0
原创粉丝点击