T1:P1115\tt T1:P1115T1:P1115
状态:dpidp_idpi 表示以 iii 为结尾的最大子段和。
状态转移方程:dpi=max(dpi−1+ai,ai)dp_i=\max(dp_{i-1}+a_i,a_i)dpi=max(dpi−1+ai,ai)
初始状态:dp1=a1dp_1=a_1dp1=a1
错误原因:开 long long,要与 aia_iai 比较,要么自己加上一个,要么自己自立门户。
T2:B3637\tt T2:B3637T2:B3637
状态:dpidp_idpi 表示以 iii 结尾的最大上升子序列。
状态转移方程:
for(int i=1;i<=n;i++)
for(int j=1;j<=i-1;j++)
if(a[i]>a[j])
dp[i]=max(dp[j]+1,dp[i]);
初始状态:dpi=1dp_i=1dpi=1
错误原因:初始状态,dpi=1dp_i=1dpi=1
做对了,所以没有\color{white}做对了,所以没有做对了,所以没有
T4:P1002\tt T4:P1002T4:P1002
状态:dpi,jdp_{i,j}dpi,j 表示起点走到 (i,j)(i,j)(i,j) 的所有路径数。
状态转移方程:
for(int i=2;i<=n;i++)
for(int j=2;j<=m;j++)
if(vis[i][j]==false)
dp[i][j]=dp[i-1][j]+dp[i][j-1];
初始状态:
先要列好方向数组,将可以走到的,第 111 行第 111 列均设为 111,注意特判 (1,1)(1,1)(1,1) 可能重复。
for(int i=0;i<=8;i++)
{
int nx=mx+dx[i];
int ny=my+dy[i];
if(nx>=1&ny>=1&&nx<=bx&&ny<=by)
vis[nx][ny]=true;
}
if(vis[1][1]==false)
dp[1][1]=1;
for(int i=2;i<=bx;i++)
if(vis[i][1]==false)
dp[i][1]=dp[i-1][1];
for(int i=2;i<=by;i++)
if(vis[1][i]==false)
dp[1][i]=dp[1][i-1];
错误原因:初始状态的第 111 行第 111 列没有处理好。
T5:P2758\tt T5:P2758T5:P2758
状态:dpi,jdp_{i,j}dpi,j 表示将 A\tt AA 串的前 iii 个字符,替换为 B\tt BB 串的前 jjj 个字符的最少操作次数。
状态转移方程:
每一个操作都用一个 dpdpdp 数组来表示。
- 删除:dpi−1,j+1dp_{i-1,j}+1dpi−1,j+1。把A\tt AA 串的第 iii 个字符删除,注意算一步 +1+1+1。
- 插入:dpi,j−1+1dp_{i,j-1}+1dpi,j−1+1。把 B\tt BB 串的第 jjj 个字符插入在 A\tt AA 串的最后面,注意算一步 +1+1+1。
- 替换:dpi−1,j−1+1dp_{i-1,j-1}+1dpi−1,j−1+1。把A\tt AA 串的前 i−1i-1i−1 个字符变为 B\tt BB 串的前 j−1j-1j−1 个字符,注意算一步 +1+1+1。
注意不变,也就是 dpi−1,j−1dp_{i-1,j-1}dpi−1,j−1。
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i]!=b[j])
dp[i][j]=min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1]))+1;
else
dp[i][j]=min(dp[i-1][j-1],min(dp[i][j-1]+1,dp[i-1][j]+1));
初始状态:
注意 i=0i=0i=0 且 j=0j=0j=0 的情况,也就是将 A\tt AA 串的前 000 个字符,替换为 B\tt BB 串的前 jjj 个字符的最少操作次数与将 A\tt AA 串的前 iii 个字符,替换为 B\tt BB 串的前 000 个字符的最少操作次数。
for(int i=1;i<=n;i++)
dp[i][0]=i;
for(int i=1;i<=m;i++)
dp[0][i]=i;
错误原因:初始状态,又是初始状态!