专题-动态规划

A - 一只小蜜蜂

HDU - 2044

状态转移方程:dp[n] = dp[n-1] + dp[n-2]

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 +10;
ll dp[60];
void init(){
	dp[1] = 1;
	dp[2] = 2;
	for(int i=3; i<60; i++){
		dp[i] = dp[i-1] + dp[i-2];
	}
}
int main(){
	init();
	int t;
	cin >> t;
	while(t--){
		int a, b;
		cin >> a >> b;
		cout << dp[b-a] << endl;
	}
	return 0;
}

B - 饭卡

HDU-2546

01背包
用5元去买最贵的商品,剩余的去01背包

#include<bits/stdc++.h>
using namespace std;
int main(){    
	int dp[1002],a[1002];
	int n,m;
	while(~scanf("%d",&n)&&n!=0){
		memset(dp,0,sizeof(dp));
		for(int i=0; i<n; i++){
			scanf("%d",&a[i]);
		}
		scanf("%d",&m);
		sort(a,a+n);
		if(m<5) cout << m <<endl;
		else {
			m-=5;
			for(int i=0; i<n-1 ;i++)
				for(int j=m;j>=a[i];j--)
					dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
			cout << m-dp[m] + 5 -a[n-1]<<endl;
		}
	}
	return 0;
}

C - 数塔

HDU - 20484

从下往上dp
每次都取最大值往上赋值

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 +10;
int dp[105][105];
int main(){
	int t, n;
	cin >> t;
	while(t--){
		cin >> n;
		memset(dp, 0, sizeof(dp));
		for(int i=1; i<=n; i++){
			for(int j=1; j<=i; j++){
				cin >> dp[i][j];
			}
		}
		for(int i=n; i>=1; i--){
			for(int j=1; j<=i; j++){
				dp[i-1][j] += max(dp[i][j], dp[i][j+1]);
			}
		}
		cout << dp[1][1] << endl;
	}
	return 0;
}

D - 最少拦截系统

HDU - 1257

从小到大遍历防导弹系统,没有能拦截的系统则重新创建一个系统。

#include <iostream>
#include<bits/stdc++.h> 

const int maxn = 1e5 + 10;
using namespace std;
int n, b[maxn];
int main(int argc, char** argv) {
	while(cin >> n){
		int cnt = 0, num;
		for(int i=0; i<n; i++){
			cin >> num;
			int j = 0;
			for( ; j<cnt; j++){
				if(num<b[j]){
					b[j] = num;
					break;
				}
			}
			if(j>=cnt){
				b[cnt++] = num;
			}
		}
		cout << cnt << endl;
	}
	return 0;
}

E - Ignatius and the Princess IV

HDU - 1029
方法一

排序取中间位置的数字即可

#include <iostream>
#include<bits/stdc++.h>

using namespace std;
const int maxn = 1e6+10;
int main(){
	int n, a[maxn];
	while(~scanf("%d", &n)){
		memset(a, 0, sizeof(a));
		for(int i=0; i<n; i++){
			scanf("%d", &a[i]);
		}
		sort(a, a+n);
		printf("%d\n", a[n/2]);
	}
    return 0;
}

方法二

dp思想:依次比较两个数,不同的就去掉,剩下的那个数既是所求的数,因为所求数的个数是大于其他数的,所以一定有所求数相连或者位于最后一个。

#include <iostream>
#include<bits/stdc++.h>

using namespace std;
const int maxn = 1e6+10;
int main(){
	int n, a[maxn];
	int dp[maxn];
	while(cin >> n){
		memset(a, 0, sizeof(a));
		memset(dp, 0, sizeof(dp));
		for(int i=0; i<n; i++) cin >> a[i];
		int i=0, j=1;
		while(j<n){
			if(dp[i]==1){
				while(dp[i]==1) i++;
			}
			if(a[i]!=a[j]){
				i++;
				dp[j++] = 1;
			}else if(a[i]==a[j]){
				while(a[i]==a[j]) j++;
			}
		}
		while(dp[i]==1) i++;
		cout << a[i] << endl;
	}
    return 0;
}

F - 免费馅饼

HDU - 1176

状态转移方程:dp[i][j] = max({dp[i-1][j],dp[i-1][j-1], dp[i-1][j+1}) + a[i][j]; 记得考虑边界情况
dp[i][j] 表示 第i秒在第j个位置所获得的最大馅饼数

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 +10;
int dp[maxn][12], a[maxn][12];

int main(){
	int n;
	while(scanf("%d",&n)!=EOF&&n){
		int x, t, maxx = 0;
		memset(a, 0, sizeof(a));
		memset(dp, 0, sizeof(dp));
		while(n--){
			scanf("%d %d", &x, &t);
			a[t][x]++; //第t秒 x位置 加一个 
			maxx = max(maxx, t); //最长时间 
		}
		dp[1][4] = a[1][4];//存好第一秒在左右获得的馅饼数 
		dp[1][5] = a[1][5];
		dp[1][6] = a[1][6];
		for(int i=2; i<=maxx; i++){//从第二秒开始 
			for(int j=0; j<11; j++){//每个位置 
				dp[i][j] = dp[i-1][j]; // 上一秒状态转移到这一秒 
				if(j>0){//不算位置0 
					dp[i][j] = max(dp[i][j], dp[i-1][j-1]); //上一秒向左移得到这一秒 
				}
				if(j<10){//不算位置10 
					dp[i][j] = max(dp[i][j], dp[i-1][j+1]); //上一秒向右移得到这一秒 
				}
				dp[i][j] += a[i][j]; 
			}
		}
		int res = 0;
		for(int i=0; i<11; i++){
			res = max(res, dp[maxx][i]);
		}
		printf("%d\n", res);
	}
	return 0;
}

G - 不容易系列之(3)—— LELE的RPG难题

HDU - 2045

状态转移方程:dp[n] = dp[n-1] + dp[n-2] * 2;
对于n个方块的情况 要考虑n-1个方块是否合理的情况

假设第n-1种情况合理
首尾不同且相邻不同,所以第n-1个和第一个确定,则第n个方格也确定颜色 dp[n] = dp[n-1];

假设第n-1种情况不合理
1.相邻相同 -->显然这种情况不存在,否则不会有n个方块
2.首尾相同,相邻不同–> n-2(红)n-1与首相同(粉/绿)则第n个方块也已经确定 dp[n] = dp[n-2] * 2;

#include <iostream>
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e6+10;
ll n, dp[maxn];
void init(){
	dp[1] = 3;
	dp[2] = 6;
	dp[3] = 6;
	for(int i=4; i<60; i++){
		dp[i] = dp[i-1] + dp[i-2] * 2;
	}
}
int main(){
	init();
	while(cin >> n){
		cout << dp[n] << endl;
	}
    return 0;
}

H - 骨牌铺方格

HDU - 2046

状态转移方程:dp[n] = dp[n-1] + dp[n-2]

前n-1确定时, 第n列只能竖着放 dp[n] = dp[n-1]
前n-2确定时,可以横着放两个 或者 竖着放两个(此情况与上面情况重复)所以 dp[n] = dp[n-2]

#include <iostream>
#include<bits/stdc++.h>
#define ll long long

using namespace std;
const int maxn = 1e6+10;
ll n, dp[maxn];
void init(){
	dp[1] = 1;
	dp[2] = 2;
	for(int i=3; i<60; i++){
		dp[i] = dp[i-1] + dp[i-2];
	}
}
int main(){
	init();
	while(cin >> n){
		cout << dp[n] << endl;
	}
    return 0;
}

I - 超级楼梯

HDU - 2041

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 +10;
ll dp[105];
void init(){
	dp[1] = 1;
	dp[2] = 1;
	for(int i=3; i<=50; i++){
		dp[i] = dp[i-1] + dp[i-2];
	}
}
int main(){
	init();
	int t, n;
	cin >> t;
	while(t--){
		cin >> n;
		cout << dp[n] << endl;
	}
	return 0;
}

J - 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

HDU - 2191

多重背包
可以转换成01背包来解决

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 +10;
int dp[105], v[105], w[105], num[105];
int main(){
	int t, n, m;
	cin >> t;
	while(t--){
		memset(dp, 0, sizeof(dp));
		cin >> n >> m;
		for(int i=1; i<=m; i++){
			cin >> v[i] >> w[i] >> num[i]; 
		}
		int res = 0;
		for(int i=1; i<=m; i++){
			for(int j=n; j>=v[i]; j--){
				for(int k=1; k<=num[i]; k++){
					if(j>=k*v[i]){  
						dp[j] = max(dp[j], dp[j-k*v[i]]+w[i]*k);
					}
				}
				res = max(res, dp[j]);
			}
		}
		cout << res << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值