诸侯安置DP做法

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


题目:

诸侯安置
【问题描述】
很久以前,有一个强大的帝国,它的国土成正方形状,如图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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值