洛谷P1240 诸侯安置 递推

本文探讨了一种类似于八皇后问题的算法挑战,但规模更大(n≤100),需要通过递推方法来解决。文章介绍了一种将不规则菱形转化为规则矩形的方法,以便更高效地进行递推计算。同时提供了完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:有一片正方形状(旋转45°看)的国土,有m个诸侯需要安置。诸侯在同一行或同一列上会互相伤害0.0,求出合理安置诸侯(使诸侯两两之间都不能攻击)的方案数对504取模的结果。(n≤100,k≤2n2-2n+1)

这张图中上面第一幅图为n=3的国土分布。下面前两幅图中两个诸侯会互相攻击,而第三幅图不会

看到这道题首先想到八皇后问题,但是n<=100,dfs会爆炸T_T。于是想到递推,但是对于这样一个菱形的国土也没有什么好的递推顺序,需要转化成更加“规则”的图形。
这里写图片描述
这样转化不会影响到最终结果,并且为递推提供了一个可行的顺序。
设f[i][j]表示前i列里安置了j个诸侯且第i列安置了诸侯的方案数,那么有
F[i][j]=sigma{f[k][j-1]*(col[i]-(j-1))} 其中 j-1<= k < i
col[i] 表示第i列有几行,在第i列之前已经放置了j-1个诸侯,也就是在第i列有j-1行不能放置诸侯,那么在第i列就有(col[i]-(j-1))个位置是可行的。
答案即为ans=sigma{f[i][m]} 其中k<=i<=n*2-1

#include <cstdio>
using namespace std;
int n,m,ans;
int col[210],f[210][210];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) col[i*2-1]=col[i*2]=i*2-1;
    if(m>n*2-2) ans=0;
    else {
        f[0][0]=1;
        for(int i=1;i<=n*2-1;i++)
            for(int j=1;j<=i;j++)
                for(int k=j-1;k<i;k++)
                    f[i][j]=(f[i][j]+f[k][j-1]*(col[i]-j+1))%504;
        for(int i=m;i<=n*2-1;i++) ans+=f[i][m];
    }
    printf("%d\n",ans%504);
    return 0;
}
### 关于 P1548 的 C++ 递推实现 #### 解题思路分析 P1548 是一道典型的动态规划或递推题目。通过观察问题的特点,可以发现其核心在于状态转移方程的设计和边界条件的处理。 对于此类问题,通常采用二维数组 `dp[i][j]` 来表示到达第 `i` 行第 `j` 列的状态值。具体来说: - **初始状态**:起点 `(1, 1)` 的值初始化为给定值或者特定逻辑下的默认值。 - **状态转移方程**:假设当前格子可以从上方或左方移动过来,则有如下关系: \[ dp[i][j] = dp[i-1][j] + dp[i][j-1] \] 此公式适用于大多数路径计数类问题[^1]。 需要注意的是,在实际编码过程中可能还需要考虑一些特殊情况,例如障碍物的存在、矩阵大小限制等。如果存在这些额外约束,则需调整相应的判断条件来跳过非法位置。 以下是基于上述理论框架编写的一个标准C++程序版本: ```cpp #include <bits/stdc++.h> using namespace std; const int MAXN = 1005; long long dp[MAXN][MAXN]; int main(){ int n,m; cin>>n>>m; // 初始化所有元素为0 memset(dp, 0, sizeof(dp)); // 起始点设置为1或其他指定初值 dp[1][1]=1; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(i==1 && j==1) continue; // 已经设定好起始点了 // 边界情况特殊处理 if(i>1){ dp[i][j] += dp[i-1][j]; } if(j>1){ dp[i][j] += dp[i][j-1]; } // 如果还有其他限制(如障碍),在此处加入过滤条件即可 } } cout<<dp[n][m]<<endl; } ``` 该代码片段实现了基本的功能需求,并且具备一定的扩展性以便后续增加更多复杂功能模块[^2]。 #### 注意事项 当面对更大规模的数据集时,单纯依靠递归来解决问题可能会遇到性能瓶颈甚至栈溢出的风险;此时改用迭代方法配合记忆化存储往往能取得更优的效果。另外也要注意变量类型的选取以防数值越界等问题发生[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值