问题描述:略。
转移方程:
F ( i , j ) = A [ i , j ] + m a x { F ( i − 1 , j ) F ( i − 1 , j − 1 ) i f j > 1 F(i, j) = A[i, j] + max \begin{cases} F(i - 1, j) \\ F(i - 1, j - 1)\quad if\quad j > 1 \end{cases} F(i,j)=A[i,j]+max{F(i−1,j)F(i−1,j−1)ifj>1
状态表示:
F(i, j)
表示从左上角走到第i
行第j
列的和得最大值。
边界:
F ( i , j ) = A [ i , j ] F(i, j) = A[i, j] F(i,j)=A[i,j]
目标:
m a x 1 ≤ j ≤ N F ( N , j ) max_{1\leq j\leq N}{F(N, j)} max1≤j≤NF(N,j)
代码:
void solve() {
int n; cin>>n;
vector<vector<int>> ph(n+1, vector<int>(n+1));
auto f(ph);
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= i; ++j) {
cin>>ph[i][j];
}
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= i; ++j) {
f[i][j] = max(f[i-1][j], f[i-1][j-1]) + ph[i][j];
}
}
cout<<*max_element(all(f[n]));
}
问题描述:略。
转移方程:
F ( i ) = m a x 0 ≤ j < i , A [ j ] < A [ i ] F [ j ] + 1 F(i) = max_{0 \leq j < i,A[j]F(i)=max0≤j<i,A[j]<A[i]F[j]+1
状态表示:
F(i)
表示前i个最上上升子序列个数
边界:
F ( 0 ) = 0 F(0) = 0 F(0)=0
目标:
m a x 1 ≤ i ≤ N F [ i ] max_{1 \leq i \leq N}{F[i]} max1≤i≤NF[i]
代码:
void solve() {
int n; cin>>n;
vector<int> a(n+1);
for(int i = 1; i <= n; ++i) cin>>a[i];
vector<int> f(n+1);
for(int i = 1; i <= n; ++i) {
f[i] = 1;
for(int j = 1; j < i; ++j) {
if(a[j] <= a[i]) f[i] = max(f[i], f[j] + 1);
}
}
cout<<*max_element(all(f));
}
void solve() {
int n; cin>>n;
vector<int> a(n);
for(auto &t: a) cin>>t;
vector<int> f;
for(auto t: a) {
auto pos = lower_bound(all(f), t);
if(pos == f.end()) f.push_back(t);
else *pos = t;
}
cout<<f.size();
}
问题描述:略。
转移方程:
F ( i , j ) = m a x { F ( i − 1 , j ) F ( i , j − 1 ) F ( i − 1 , j − 1 ) i f A [ i ] = B [ i ] F(i, j) = max \begin{cases} F(i - 1, j) \\ F(i, j - 1) \\ F(i - 1, j - 1) \quad if \quad A[i] = B[i] \end{cases} F(i,j)=max⎩ ⎨ ⎧F(i−1,j)F(i,j−1)F(i−1,j−1)ifA[i]=B[i]
状态表示:
在A串的第i个和B串的第j个中的最长公共子序列
边界:
F ( i , 0 ) = F ( 0 , j ) = 0 F(i, 0) = F(0, j) = 0 F(i,0)=F(0,j)=0
目标:
F ( N i , M j ) F(N_{i}, M_{j}) F(Ni,Mj)
代码:
// 字符串和数字对于这题来说相同
void solve() {
int n; cin>>n;
vector<int> A(n+1);
auto B(A);
vector<vector<int>> f(n+1, vector<int>(n+1));
rep(i,1,n) cin>>A[i];
rep(i,1,n) cin>>B[i];
rep(i,1,n) {
rep(j,1,n) {
f[i][j] = max(f[i-1][j], f[i][j-1]);
if(A[i] == B[j]) f[i][j] = max(f[i][j], f[i-1][j-1] + 1);
}
}
cout<<f[n][n];
}
问题描述:略。
转移方程:
F ( i , j ) = { 0 i f p h [ i , j ] = 马能到达位置 F ( i − 1 , j ) + F ( i , j − 1 ) F(i, j) = \begin{cases} 0 \quad if \quad ph[i,j] = 马能到达位置 \\ F(i-1,j) + F(i,j-1) \end{cases} F(i,j)={0ifph[i,j]=马能到达位置F(i−1,j)+F(i,j−1)
状态表示:
F(i,j)
表示从0,0点到坐标(i,j)的路径之和。
边界:
F ( 0 , 0 ) = 1 F(0,0) = 1 F(0,0)=1
目标:
F ( N , N ) F(N,N) F(N,N)
代码:
void solve() {
int x1,x2,y1,y2; cin>>x1>>y1>>x2>>y2;
x1++,y1++,x2++,y2++;
vector<vector<int>> f(x1+1, vector<int>(y1+1));
vector<int> fx({-1,-1,1,1,2,2,-2,-2}), fy({2,-2,2,-2,1,-1,1,-1});
for(int i = 0; i < 8; ++i) {
int xx = x2 + fx[i], yy = y2 + fy[i];
if(xx < 1 || xx > x1 || yy < 1 || yy > y1) continue;
f[xx][yy] = -1;
}
f[x2][y2] = -1;
// f[0][2] = f[2][0] = 1;
for(int i = 1; i <= x1; ++i) {
for(int j = 1; j <= y1; ++j) {
if(i == 1 && j == 1) {
f[i][j] = 1; continue;
}
if(f[i][j] == -1) f[i][j] = 0;
else f[i][j] = f[i-1][j] + f[i][j-1];
// cout<
}
}
cout<<f[x1][y1];
}
luogu数据:
in: 8 6 0 4
out: 1617
错误原因:判断方向continue错了,xx > x2 || yy > y2
,原来是xx >= x2 || yy >= y2
。
问题描述:传球游戏,开始球在第一个人处,问经过m次传球,传到第一个人处的方法数。
转移方程:
F ( j = = 1 ? n : j − 1 , i ) + = F ( j , i − 1 ) F ( j = = n ? 1 : j + 1 , i ) + = F ( j , i − 1 ) F(j == 1 ? n : j -1 ,i) += F(j, i - 1)\\ F(j == n ? 1 : j + 1, i) += F(j, i - 1) F(j==1?n:j−1,i)+=F(j,i−1)F(j==n?1:j+1,i)+=F(j,i−1)
状态表示:
F(j,i)
表示从0到第i次传到第j个人的方法数。因为是成环,需要在左右边界进行特判。
边界:
F ( 1 , 0 ) = 1 F(1,0) = 1 F(1,0)=1
目标:
F ( 1 , m ) F(1,m) F(1,m)
代码:
void solve() {
int n,m; cin>>n>>m;
vector<vector<int>> f(n+1, vector<int>(m+1));
f[1][0] = 1;
rep(i,1,m) { // **
rep(j,1,n) {
f[j == 1 ? n : j - 1][i] += f[j][i-1];
f[j == n ? 1 : j + 1][i] += f[j][i-1];
}
}
cout<<f[1][m];
}
错误原因
问题描述:给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。
转移方程:
F ( i ) = m a x ( A [ i ] , F ( i − 1 ) + A [ i ] ) F(i) = max(A[i], F(i-1) + A[i]) F(i)=max(A[i],F(i−1)+A[i])
状态表示:
F(i)
表示的是前i个连续的最大字段和。
边界:
F ( 1 ) = A [ 1 ] F(1) = A[1] F(1)=A[1]
目标:
m a x 1 ≤ i ≤ N F ( i ) max_{1 \leq i \leq N}{F(i)} max1≤i≤NF(i)
代码:
void solve() {
int n; cin>>n;
vector<LL> a(n+1);
for(int i = 1; i <= n; ++i) cin>>a[i];
vector<LL> f(n+1);
f[1] = a[1];
for(int i = 2; i <= n; ++i) {
f[i] = max(a[i], f[i-1] + a[i]);
}
cout<<*max_element(f.begin()+1, f.end());
}