主题:背包
背包是利用动态规划
主要形式:
1.一维形式
int v[100],n,w[100],dp[100];
memset(dp,0,sizeof(dp));
for(int i = 1; i <= n; i++){
for(int j = m; j >= w[i]; j--){
dp[j] = max(dp[j],dp[j - w[i]]+v[i]);
}
}
printf("%d", dp[m]);//从大到小保持不会爆
2.二维形式
函数实现 0-1 背包
#include<cstdlib>
#include<cstdio>
using namespace std;
int V[3500][15000];//在main函数外面能把一/二维数组开的更大一些
int knapSack(int n, int m, int *w, int *v){
for(int i = 0'; i < n; i++){
V[0][i] = 0;
}
for(int i = 0; i < m; ++){
v[i][0] = 0;
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m]; j--){
if(j < w[i]){
V[i][j] = V[i-1][j];
}
else {
V[i][ j] =max(V[i-1][j],V[i-1][j+w[i]]+v[i]);
}
}
}
int j = m;
for(int i =n ;i > 0; i--){
if(V[i][j] > V[i][j-1]){
j = j - w[i];
}
else ;
}
return V[n][m];
}
int main(){
itn n, m,w[500],v[500];
memset(V,0,sizeof(V));
while(~scanf("%d%d", &n,&m)){
for(int i = 1; i <= n; i++){
scanf("%d%d", &w[i], &v[i]);
printf("%d\n", KsnapSack(n,m,w,v));
}
return 0;
}
3.背包不一定为+,还可变形为×
for(int i = 1; i <= n ; i++)
for(int j = m; j >= w[i] ; j--)
.... = max( , )
只是为了得到最接近m的组合
4.二维数组可以用下标来表示一个平衡状态
如果i下标会小于零的话,重新定义一个零点.
例http://acm.hust.edu.cn/vjudge/contest/view.action?cid=69281#problem/Cbalance
定义7500为零点.
dp[0][7500] = 1;//m表示砝码的个数,n表示距离中心的距离的个数
for(int i = 1; i <=n; i++){
for(int j = 1; j <= m; j++){
for(int k = 0; k <= 15000; k++){
dp[i][k + w[i]*v[j]]+=dp[i-1][k];
}
}
}
printf("%d", dp[m][7500]);
5.最长不下降子序列
一.n*2复杂度的一般做法(大于10000个元素时不再适用)
#include<stdio.h>
int main(){
int num[100],a[100];
int n;
scanf("%d", &n)
for(int i = 0; i <= n; i++){
scanf("%d", &a[i]);
}
for(int i = 0; i <= n; i++){
num[i] = 1;
for(int j = 0; j < i; j++){
if(a[i] > a[j]&&num[j]+1>num[i]){
num[i] = num[j] +1;
}
}
int max = 0;
for(int i = 0; i < n; i++){
if(max < a[i])
max = a[i];
}
printf("%d\n", max);
}
return 0;
}
二.二分法 复杂度n*logn
int a[10000],num[10000];
int find(int len ,int n){
int left = 1, right = len;
int mid;
whie(left<=right){
if(a[mid] = n) return mid;
else if(a[mid] > n) right = mid - 1;
else if(a[mid] < n) left = mid + 1;
}
return left;
}
int main(){
int n;
while(~scanf("%d", &n)){
for(itn i = 1; i <= n; i++){
scanf("%d", a[i]);
}
num[1] = a[1];
int len = 1;
for(int i = 1; i <= n; i++){
int j = find(len ,a[i]);
num[j] = a[i];
if(j > len)
len = j;
}
printf("%d\n", len);
}
return 0;
}