今天讲的全是dp...
不多废话,先看一道经典的模板LIS(最长不下降子序列)
一.LIS
给定一个长度为N的数列,求最长上升子序列
例:1 7 2 8 3 4
答案:1 2 3 4
代码:
1 #include <bits/stdc++.h>//突然想用万能库 2 3 using namespace std; 4 5 const int maxn = 100000; 6 int n, data[maxn], dp[maxn], from[maxn];//方案 7 void output(int x) 8 { 9 if(!x) return ; 10 output(from[x]); 11 cout<<data[x]<<" "; 12 } 13 int main() 14 { 15 cin>>n; 16 for(int i = 1; i <= n;i++) cin>>data[i]; 17 18 for(int i = 1; i <= n;i++) 19 { 20 dp[i] = 1; 21 from[i] = 0; 22 for(int j = 1; j < i; j++) 23 { 24 if(data[j] < data[i]&&dp[j]+1 > dp[i]) 25 { 26 dp[i] = dp[j] + 1; 27 from[i] = j; 28 } 29 } 30 } 31 32 int ans = dp[1], pos = 1; 33 for(int i = 1; i <= n; i++) 34 if(ans < dp[i]) 35 { 36 ans = dp[i]; 37 pos = i; 38 } 39 cout<<ans<<endl; 40 output(pos); 41 return 0; 42 }
二.背包问题
背包就不多讲了,背包九讲里面非常明白了,也是很基础的dp
N个物品,每个物品有价值和体积两个属性
从中选出若干个物品,体积和不超过V 要求选出的物品价值和最大
每个物品只能选一次(01背包)
体积可能是多维(多维背包)
物品可以被选的次数可能是有限次或者无限次(完全背包)
物品之间可能存在依赖(依赖背包)
......
三.ST表
思想:倍增、DP(状态转移方程: F[i,j] = min/max (F[i,j - 1],F[i + 2^(j - 1),j - 1]) )
功能:求任意区间的最大值
要求:静态的,无法修改数据
空间复杂度:O(nlogn)
时间复杂度:O(nlogn) – O(1)
#include <cstdio> #include <algorithm> using namespace std; int const maxn = 1000000; int st[maxn][20], a[maxn], ans[maxn]; int n, m, left, right, j, i; int main() { scanf("%d%d", &n, &m); for(i = 1; i <= n; i++) { scanf("%d", &a[i]); st[i][0] = a[i]; } for(j = 1; (1<<j) <= n; j++) for(i = 1; i <= n-(1<<j) + 1; i++) st[i][j] = min(st[i][j-1] , st[i+( 1<<(j-1) )][j-1]); for(i = 1; i <= m; i++) { scanf("%d%d", &left, &right); j = 0; while((1<<(j+1)) <= (right-left+1)) j++; ans[i] = min(st[left][j],st[right-(1<<j)+1][j]); } for(i = 1; i <= m; i++) printf("%d ",ans[i]); return 0; }
还有一部分...待我再细细思考总结...(说白了就是现在还不太明白)