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;
}