1.max plus plus
思路:设dp[i][j]为以j结尾分为i分的最大值
状态转移方程:dp[i][j]=max(dp[i][j-1],max(dp[i-1][k])(k<=j-1)+a[j]
1.由于数据过大,进行滚动数组优化
2.max(dp[i-1][k])==dp[i-2][j-1]==pre,可对上次结果保存处理
#include <iostream>
#include <map>
#include <algorithm>
#include <string.h>
#define ll long long
#define pq priority_queue
#define repr(i, x, y) for (int i = x; i <= y; i++)
#define rep(i, x, y) for (int i = x; i < y; i++)
#define drep(i, x, y) for (int i = x; i >= y; i--)
#define pb push_back
#define P make_pair
#define pii pair<int, int>
#define mem(x, y) memset(x, y, sizeof(x))
using namespace std;
const int inf = 0x3f3f3f3f , maxn = 2e5 + 5 ;
const double eps = 1e-8 ;
int a[ 1000005 ] , dp[ 1000005 ] , l[ 1000005 ] ;
int main ( ) {
int n, m;
while ( ~ scanf ( "%d%d" , & m, & n) ) {
mem ( dp, 0 ) , mem ( l, 0 ) ;
repr ( i, 1 , n) scanf ( "%d" , & a[ i] ) ;
int maxx;
repr ( i, 1 , m) {
maxx= - ( 1 << 30 ) ;
repr ( j, i, n) {
dp[ j] = max ( dp[ j- 1 ] , l[ j- 1 ] ) + a[ j] ;
l[ j- 1 ] = maxx;
maxx= max ( maxx, dp[ j] ) ;
}
}
printf ( "%d\n" , maxx) ;
}
return 0 ;
}
2. super jumping
思路:线性dp
状态转移方程:dp[i]=max(dp[j])+a[i](j<i&&a[i]>a[j])
#include <iostream>
#include <string.h>
#include <algorithm>
#define ll long long
#define pq priority_queue
#define repr(i, x, y) for (int i = x; i <= y; i++)
#define rep(i, x, y) for (int i = x; i < y; i++)
#define drep(i, x, y) for (int i = x; i >= y; i--)
#define pb push_back
#define P make_pair
#define pii pair<int, int>
#define mem(x, y) memset(x, y, sizeof(x))
using namespace std;
const int inf = 0x3f3f3f3f , maxn = 2e5 + 5 ;
const double eps = 1e-8 ;
int dp[ maxn] , a[ maxn] ;
int main ( ) {
int n;
while ( cin>> n&& n) {
mem ( dp, 0 ) ;
repr ( i, 1 , n) cin>> a[ i] , dp[ i] = a[ i] ;
int ans= 0 ;
repr ( i, 1 , n) {
repr ( j, i+ 1 , n) {
if ( a[ j] > a[ i] ) dp[ j] = max ( dp[ j] , dp[ i] + a[ j] ) ;
}
ans= max ( ans, dp[ i] ) ;
}
cout<< ans<< '\n' ;
}
return 0 ;
}
3.最少拦截系统
思路:贪心加二分
为使当前序列更有潜力进行上升,在线操作二分,每次进行替换。
1.dp初始化为inf
2.本方法只能求得长度
#include <iostream>
#include <map>
#include <algorithm>
#include <string.h>
#define ll long long
#define pq priority_queue
#define repr(i, x, y) for (int i = x; i <= y; i++)
#define rep(i, x, y) for (int i = x; i < y; i++)
#define drep(i, x, y) for (int i = x; i >= y; i--)
#define pb push_back
#define P make_pair
#define pii pair<int, int>
#define mem(x, y) memset(x, y, sizeof(x))
using namespace std;
const int inf = 0x3f3f3f3f , maxn = 2e5 + 5 ;
const double eps = 1e-8 ;
int a[ maxn] , dp[ maxn] ;
int main ( ) {
int n;
while ( cin>> n) {
mem ( dp, inf) ;
repr ( i, 1 , n) cin>> a[ i] , * lower_bound ( dp+ 1 , dp+ n+ 1 , a[ i] ) = a[ i] ;
printf ( "%d\n" , lower_bound ( dp+ 1 , dp+ n+ 1 , inf) - dp- 1 ) ;
}
return 0 ;
}
4. common subsequence
思路:设dp[i][j]为a长i,b长j时最长公共子序列
状态转移方程:a[i]==b[j]: dp[i+1][j+1]=dp[i][j]+1
else: dp[i+1][j+1]=max(dp[i][j+1]),dp[i+1][j])
#include <iostream>
#include <algorithm>
#include <string.h>
#include <cstring>
#define ll long long
#define pq priority_queue
#define repr(i,x,y) for(int i=x;i<=y;i++)
#define rep(i,x,y) for(int i=x;i<y;i++)
#define drep(i,x,y) for(int i=x;i>=y;i--)
#define pb push_back
#define P make_pair
#define pii pair<int,int>
#define mem(x,y) memset(x,y,sizeof(x))
using namespace std;
const int inf = 0x3f3f3f3f , maxn = 2e5 + 5 ;
const double eps = 1e-8 ;
string a, b;
int dp[ 1005 ] [ 1005 ] ;
int main ( ) {
std:: ios:: sync_with_stdio ( false ) ;
cin. tie ( 0 ) ;
while ( cin>> a>> b) {
mem ( dp, 0 ) ;
rep ( i, 0 , a. size ( ) ) {
repr ( j, 0 , b. size ( ) ) {
if ( a[ i] == b[ j] ) {
dp[ i+ 1 ] [ j+ 1 ] = dp[ i] [ j] + 1 ;
}
else {
dp[ i+ 1 ] [ j+ 1 ] = max ( dp[ i] [ j+ 1 ] , dp[ i+ 1 ] [ j] ) ;
}
}
}
cout<< dp[ a. size ( ) ] [ b. size ( ) ] << '\n' ;
}
return 0 ;
}
5.Phalanx
思路:最大对称子矩阵,设dp[i][j]为(i,j)点向上向右扩张最大子矩阵
1.初始化dp为1,每次遍历出无法扩张的结尾
2.状态转移方程:dp[i][j]=min(dp[i-1][j+1],i-ii+1)+1(ii为遍历结尾)
#include <iostream>
#include <algorithm>
#include <string.h>
#define ll long long
#define pq priority_queue
#define repr(i,x,y) for(int i=x;i<=y;i++)
#define rep(i,x,y) for(int i=x;i<y;i++)
#define drep(i,x,y) for(int i=x;i>=y;i--)
#define pb push_back
#define P make_pair
#define pii pair<int,int>
#define mem(x,y) memset(x,y,sizeof(x))
using namespace std;
const int inf = 0x3f3f3f3f , maxn = 2e5 + 5 ;
const double eps = 1e-8 ;
int n;
int dp[ 2005 ] [ 2005 ] ;
char a[ 2005 ] [ 2005 ] ;
int main ( ) {
while ( ~ scanf ( "%d" , & n) && n) {
repr ( i, 1 , n) {
repr ( j, 1 , n) {
cin>> a[ i] [ j] ;
}
}
mem ( dp, 0 ) ;
int ans= 1 ;
repr ( i, 1 , n) {
repr ( j, 1 , n) {
dp[ i] [ j] = 1 ;
int ii= i- 1 , jj= j+ 1 ;
while ( a[ i] [ jj] == a[ ii] [ j] && ii&& jj<= n) {
ii-- , jj++ ;
}
dp[ i] [ j] = min ( dp[ i- 1 ] [ j+ 1 ] , i- ii- 1 ) + 1 ;
ans= max ( ans, dp[ i] [ j] ) ;
}
}
cout<< ans<< '\n' ;
}
return 0 ;
}
6.免费馅饼
思路:设dp[i][j]为i时刻j位置可获得最大馅饼数
1.因无法得到后时刻最大获得数,故倒序dp
2.状态转移方程dp[i][j]=max(dp[i+1][j],dp[i+!][j-1],dp[i+1][j+1])(防止位置负数,对其加1操作)
#include <iostream>
#include <algorithm>
#include <string.h>
#define ll long long
#define pq priority_queue
#define repr(i,x,y) for(int i=x;i<=y;i++)
#define rep(i,x,y) for(int i=x;i<y;i++)
#define drep(i,x,y) for(int i=x;i>=y;i--)
#define pb push_back
#define P make_pair
#define pii pair<int,int>
#define mem(x,y) memset(x,y,sizeof(x))
using namespace std;
const int inf = 0x3f3f3f3f , maxn = 2e5 + 5 ;
const double eps = 1e-8 ;
int n;
int dp[ maxn] [ 15 ] ;
int a[ maxn] [ 15 ] ;
int main ( ) {
while ( ~ scanf ( "%d" , & n) && n) {
int maxx= - 1 ;
mem ( dp, 0 ) , mem ( a, 0 ) ;
int x, y;
repr ( i, 1 , n) {
scanf ( "%d%d" , & x, & y) ;
a[ y] [ ++ x] ++ ;
maxx= max ( maxx, y) ;
}
drep ( i, maxx, 0 ) {
repr ( j, 1 , 11 ) {
dp[ i] [ j] = max ( dp[ i+ 1 ] [ j+ 1 ] , max ( dp[ i+ 1 ] [ j] , dp[ i+ 1 ] [ j- 1 ] ) ) + a[ i] [ j] ;
}
}
printf ( "%d\n" , dp[ 0 ] [ 6 ] ) ;
}
return 0 ;
}
7.Tickets
思路:简单dp,注意格式
1.状态转移方程:dp[i]=min(dp[i-1]+a[i],dp[i-2]+b[i])
#include <iostream>
#include <algorithm>
#include <string.h>
#define ll long long
#define pq priority_queue
#define repr(i,x,y) for(int i=x;i<=y;i++)
#define rep(i,x,y) for(int i=x;i<y;i++)
#define drep(i,x,y) for(int i=x;i>=y;i--)
#define pb push_back
#define P make_pair
#define pii pair<int,int>
#define mem(x,y) memset(x,y,sizeof(x))
using namespace std;
const int inf = 0x3f3f3f3f , maxn = 2e5 + 5 ;
const double eps = 1e-8 ;
int dp[ maxn] , a[ maxn] , b[ maxn] ;
int n, k;
int main ( ) {
cin>> n;
while ( n-- ) {
cin>> k;
repr ( i, 1 , k) cin>> a[ i] ;
repr ( i, 2 , k) cin>> b[ i] ;
dp[ 1 ] = a[ 1 ] ;
repr ( i, 2 , k) {
dp[ i] = min ( dp[ i- 1 ] + a[ i] , dp[ i- 2 ] + b[ i] ) ;
}
int h= 8 , min= 0 , sec= 0 ;
sec+ = dp[ k] ;
min+ = sec/ 60 % 60 ;
h+ = sec/ 3600 ;
sec% = 60 ;
printf ( "%02d:%02d:%02d " , h, min, sec) ;
if ( h>= 12 ) puts ( "pm" ) ;
else puts ( "am" ) ;
}
return 0 ;
}
8.FatMouse and Cheese
思路:记忆化搜索
1.设dp[x][y]为x,y点获得最大值
2.若以更新过则直接返回
3.dp[i][j]=max(dp上下左右)(if满足条件)
#include <iostream>
#include <algorithm>
#include <string.h>
#define ll long long
#define pq priority_queue
#define repr(i,x,y) for(int i=x;i<=y;i++)
#define rep(i,x,y) for(int i=x;i<y;i++)
#define drep(i,x,y) for(int i=x;i>=y;i--)
#define pb push_back
#define P make_pair
#define pii pair<int,int>
#define mem(x,y) memset(x,y,sizeof(x))
using namespace std;
const int inf = 0x3f3f3f3f , maxn = 2e5 + 5 ;
const double eps = 1e-8 ;
int n, m;
int dp[ 2005 ] [ 2005 ] ;
int a[ 2005 ] [ 2005 ] ;
int d[ 4 ] [ 2 ] = { 1 , 0 , - 1 , 0 , 0 , 1 , 0 , - 1 } ;
int dfs ( int x, int y) {
if ( dp[ x] [ y] ) return dp[ x] [ y] ;
int ans= 0 ;
repr ( i, 1 , m) {
rep ( j, 0 , 4 ) {
int xx= x+ d[ j] [ 0 ] * i, yy= y+ d[ j] [ 1 ] * i;
if ( a[ x] [ y] < a[ xx] [ yy] && xx> 0 && yy> 0 && xx<= n&& yy<= n) {
ans= max ( dfs ( xx, yy) , ans) ;
}
}
}
return dp[ x] [ y] = a[ x] [ y] + ans;
}
int main ( ) {
while ( ~ scanf ( "%d%d" , & n, & m) && n!= - 1 && m!= - 1 ) {
repr ( i, 1 , n) {
repr ( j, 1 , n) {
cin>> a[ i] [ j] ;
}
}
mem ( dp, 0 ) ;
cout<< dfs ( 1 , 1 ) << '\n' ;
}
return 0 ;
}