DP问题已知思路情况下写错了如何Debug

本文通过一个删除最小元素的DP问题实例,探讨了在已知DP思路但实现错误时的调试方法。建议在循环中输出DP矩阵进行检查,并强调先在草稿纸上写出状态方程以降低错误率。

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

以计蒜客CS109 删除最小元素习题为例:

给定有 nn 个数的 AA 序列:A_1,A_2,A_3\cdots A_nA1,A2,A3An。对于这个序列,我们想得到一个子序列 A_{p_1}, A_{p_2} \cdots A_{p_i} \cdots A_{p_m}(1 \le p_1 < p_2<\cdots p_i < \cdots < p_m \le n)Ap1,Ap2ApiApm(1p1<p2<pi<<pmn),满足 A_{p_1} \ge A_{p_2} \ge \cdots \ge A_{p_i} \le \cdots \le A_{p_m}Ap1Ap2ApiApm。从 AA 序列最少删除多少元素,可以得到我们想要的子序列。

输入格式

第一行输入一个整数 nn,代表 AA 序列中数字的个数。第二个输入 nn 个整数,代表A_1,A_2,A_3...A_nA1,A2,A3...An

(1 \leq n \leq 10001n10001 \leq A_i \leq 100001Ai10000)

输出格式

输出需要删除的元素个数,占一行。

样例输入
7
3 2 4 1 2 5 3
样例输出
2

啊这道题目思路比较简单,就是从左往右一次LDS最大递减子序列和从中间到末端LCS最大递增子序列,2次DP。思路比较简单,但写了好久都没写对,一直不知道问题出在哪里。然后总结了下这类DP问题有思路但结果错误情况下的Debug通法,直接在循环里面加上输出DP矩阵的语句,然后逐行检查,一般都能找到哪里写错了。另外最好在草稿纸上先把状态方程写下来,我习惯不太好有时候图省事总是直接写代码,这样错误率也比较高。


下面附上这题代码:

#include<bits/stdc++.h>
using namespace std;
int dp[1003][1003]; 
int dp1[1003][1003];
int dp2[1003][1003];
int a[1003];

int main(void){
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<=i;j++){
			dp1[j][i]=1;
			dp2[j][i]=1;
		}
	}


	for(int m=0;m<n;m++){
		for(int i=0;i<=m;i++){
			for(int j=0;j<i;j++){
				if(a[j]>=a[i]){
					dp1[i][m]=max(dp1[i][m],dp1[j][m]+1);
				}
			}
		//cout<<dp1[i][m]<<" ";
		}//cout<<endl;
	}
	
	for(int m=0;m<n;m++){
		for(int i=0;i<=m;i++){
			for(int j=i;j<m;j++){
				if(a[j]<=a[m]){
					dp2[i][m]=max(dp2[i][m],dp2[i][j]+1);
				}
			}
			//cout<<dp2[i][m]<<" ";
		}//cout<<endl;   //就是这两行cout,非常重要
	}
	
	int max1=-99999;
	
	for(int i=0;i<n;i++){
		for(int j=0;j<=i;j++){
			dp[j][i]=dp1[j][i]+dp2[j][i];
			max1=max(max1,dp[j][i]);
		//	cout<<dp2[j][i]<<" ";
		}//cout<<endl;   
	}
	cout<<n+1-max1<<endl;

	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值