HDU 1024 Max Sum Plus Plus
题意
你有n个数s1, s2…sn,给你一个整数m,求m个子段和的最大值
思路
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e6 + 10;
const int inf = 0x7ffffff;
int a[maxn];
int f[maxn];
int Max[maxn];
int main() {
int n, m, mmax;
while(~scanf("%d%d", &m, &n)) {
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
}
memset(f, 0, sizeof f);
memset(Max, 0, sizeof Max);
for(int i = 1; i <= m; i ++) {
mmax = -inf;
for(int j = i; j <= n; j ++) {
f[j] = f[j - 1];
f[j] = max(f[j - 1] + a[j], Max[j - 1] + a[j]);
// 用Max[i] 保存i - 1组 考虑前j-1个数的最大值, 降低了一层循环
Max[j - 1] = mmax;
mmax = max(mmax, f[j]);
}
}
printf("%d\n", mmax);
}
return 0;
}
HDU1029Ignatius and the Princess IV
思路
摩尔投票算法
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1000010;
int a[N];
int n, x, num, cnt;
int main() {
int n;
while(~scanf("%d", &n)) {
num = 0, cnt = 0;
for(int i = 1; i <= n; i ++) {
cin >> x;
if(x == num) cnt ++;
else {
if(cnt == 0) {cnt ++, num = x;}
else cnt --;
}
}
cout << num << endl;
}
return 0;
}
HDU1069 Monkey and Banana
思路
简单的LIS,只不过判断的时候要判断两个属性,宽和高
注意
next_permutation用法
sort(a , a + n); //这里忘了,导致全排列没求完整
do {
}while(next_permutation(a, a + n))
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010;
struct Brick{
int x, y, z;
}brick[N];
int n;
int num[3];
int f[N];
bool cmp(Brick a, Brick b) {
if(a.x == b.x)
return a.y < b.y;
return a.x < b.x;
}
int main(){
int k = 1;
while(~scanf("%d", &n)) {
if(!n) break;
int cnt = 0;
for(int i = 0; i < n; i ++) {
int a, b, c;
cin >> a >> b >> c;
num[0] = a, num[1] = b, num[2] = c;
sort(num, num + 3);
do {
brick[cnt].x = num[0], brick[cnt].y = num[1], brick[cnt].z = num[2], cnt ++;
}while(next_permutation(num, num +3));
}
sort(brick, brick + cnt, cmp);
memset(f, 0, sizeof f);
int ans = 0;
for(int i = 0; i < cnt; i ++){
f[i] = brick[i].z;
for(int j = 0; j < i; j ++) {
if(brick[j].x < brick[i].x && brick[j].y < brick[i].y) {
f[i] = max(f[i], f[j] + brick[i].z);
}
}
ans = max(ans, f[i]);
}
printf("Case %d: maximum height = %d\n", k ++, ans);
}
return 0;
}
HDU 1087 Super Jumping! Jumping! Jumping
思路
LIS模板题
代码
在这里插入代码片#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010;
int f[N];
int ans;
int a[N];
int main() {
int n;
while(~scanf("%d", &n) && n) {
for(int i = 0; i < n; i ++)
scanf("%d", &a[i]);
memset(f, 0, sizeof f);
ans = 0;
for(int i = 0; i < n; i ++) {
f[i] = a[i];
for(int j = 0; j < i; j ++) {
if(a[j] < a[i]) {
f[i] = max(f[i], f[j] + a[i]);
}
}
ans = max(ans, f[i]);
}
cout << ans << endl;
}
return 0;
}
HDU 1114 Piggy-Bank
思路
完全背包模板题咯
状态表示:
f
[
i
]
[
j
]
:
考
虑
前
i
个
物
品
,
体
积
恰
好
为
j
的
所
有
选
法
f[i][j]:考虑前i个物品, 体积恰好为j的所有选法
f[i][j]:考虑前i个物品,体积恰好为j的所有选法
属性:
m
i
n
min
min
状态计算(滚动数组):
f
[
j
]
=
m
i
n
(
f
[
j
]
,
f
[
j
−
v
]
+
w
)
f[j] = min(f[j], f[j - v] + w)
f[j]=min(f[j],f[j−v]+w)
初始化:
f
[
0
]
=
0
,
f[0] = 0,
f[0]=0, 其他
f
[
i
]
=
+
∞
f[i] = +∞
f[i]=+∞
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 510, M = 10010;
int w, v;
int f[M];
int main() {
int T;
scanf("%d", &T);
while(T --) {
memset(f, 0x3f, sizeof f);
int a, b;
scanf("%d%d", &a, &b);
int m = b - a;
int n;
scanf("%d", &n);
f[0] = 0;
for(int i = 1; i <= n; i ++) {
scanf("%d%d", &w, &v);
for(int j = 0; j <= m; j ++) {
if(j >= v) f[j] = min(f[j], f[j - v] + w);
}
}
if(f[m] != 0x3f3f3f3f) printf("The minimum amount of money in the piggy-bank is %d.\n", f[m]);
else puts("This is impossible.");
}
return 0;
}
HDU 1176 免费馅饼
思路
数塔问题, DP倒着推
状态表示
f
[
i
]
[
j
]
f[i][j]
f[i][j]: 走了
i
i
i秒, 且当前位置在
j
j
j的所有走法
属性:
m
a
x
max
max
状态计算:
f
[
i
]
[
j
]
=
m
a
x
(
f
[
i
+
1
]
[
j
−
1
]
,
m
a
x
(
f
[
i
+
1
]
[
j
]
,
f
[
i
+
1
]
[
j
+
1
]
)
)
+
a
[
i
]
[
j
]
;
f[i][j] = max(f[i + 1][j - 1], max(f[i + 1][j], f[i + 1][j + 1])) + a[i][j];
f[i][j]=max(f[i+1][j−1],max(f[i+1][j],f[i+1][j+1]))+a[i][j];
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100010;
int f[N][15];
int a[N][15];
int main() {
int n;
while(~scanf("%d", &n) && n) {
memset(a, 0, sizeof a);
memset(f, 0, sizeof f);
int maxx = 0;
for(int i = 0; i < n; i ++) {
int p, t;
scanf("%d%d", &p, &t);
// 坐标向右偏移一个位置
a[t][++ p] ++;
maxx = max(maxx, t);
}
for(int i = maxx; i >= 0; i --) {
for(int j = 1; j <= 11; j ++){
f[i][j] = max(f[i + 1][j - 1], max(f[i + 1][j], f[i + 1][j + 1])) + a[i][j];
}
}
printf("%d\n", f[0][6]);
}
return 0;
}
HDU1260 Tickets
思路
状态表示
f
[
i
]
f[i]
f[i]: 前i个人买完的所有买法
属性:
m
i
n
min
min
状态计算:
f
[
i
]
=
m
i
n
(
f
[
i
−
1
]
+
a
[
i
]
,
f
[
i
−
2
]
+
b
[
i
]
)
;
f[i] = min(f[i - 1] + a[i], f[i - 2] + b[i]);
f[i]=min(f[i−1]+a[i],f[i−2]+b[i]);
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2010;
int a[N], b[N];
int f[N];
int main() {
int n, T;
scanf("%d", &T);
while(T --) {
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
scanf("%d", &a[i]);
for(int i = 2; i <= n; i ++)
scanf("%d", &b[i]);
f[0] = 0;
f[1] = a[1];
for(int i = 2; i <= n; i ++)
f[i] = min(f[i - 1] + a[i], f[i - 2] + b[i]);
int h = 8;
h += f[n] / 3600;
int m = f[n] / 60 % 60;
int s = f[n] % 60;
if(h < 12) {
printf("%02d:%02d:%02d am\n", h, m, s);
}
else {
printf("%02d:%02d:%02d pm\n", h - 12, m, s);
}
}
return 0;
}
HDU1257最少拦截系统
思路
贪心可过, 能放就放, 不能新开一个导弹系统
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e6 + 10;
int a[N], q[N];
int main() {
int n;
while(~scanf("%d", &n)) {
int cnt = 0;
for(int i = 0; i < n; i ++) {
scanf("%d", &a[i]);
int k = 0;
while(k < cnt && q[k] < a[i]) k ++;
if(k == cnt) q[cnt ++] = a[i];
else q[k] = a[i];
}
printf("%d\n", cnt);
}
return 0;
}
HDU1160 FatMouse’s Speed
思路
LIS, 输出路径采用倒着枚举,妙啊
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010;
int f[N];
struct Mouse {
int id;
int w;
int speed;
}mouse[N];
bool cmp(Mouse a, Mouse b) {
if(a.w == b.w) return a.speed > b.speed;
return a.w < b.w;
}
int main() {
int w, speed;
int cnt = 0;
while(~scanf("%d%d", &w, &speed)) {
mouse[cnt].id = cnt + 1, mouse[cnt].w = w, mouse[cnt].speed = speed;
cnt ++;
}
sort(mouse, mouse + cnt, cmp);
int ans = 0;
for(int i = cnt - 1; i >= 0; i --) {
f[i] = 1;
for(int j = i + 1; j < cnt; j ++) {
if(mouse[i].w < mouse[j].w && mouse[i].speed > mouse[j].speed) {
f[i] = max(f[i], f[j] + 1);
}
}
ans = max(ans, f[i]);
}
printf("%d\n", ans);
for(int i = 0; i < cnt; i ++)
if(f[i] == ans) {
printf("%d\n", mouse[i].id);
ans --;
}
return 0;
}
POJ 3186 Treats for the Cows
思路
区间DP, 逆着来, 当长度是1的时候,当它是最后一个选的
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2010;
int f[N][N];
int a[N];
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
scanf("%d", &a[i]);
for(int len = 1; len <= n; len ++)
for(int i = 1; i + len - 1 <= n; i ++) {
int l = i, r = i + len - 1;
f[l][r] = 1e8;
if(l == r) f[l][r] = a[l] * n;
else {
f[l][r] = max(f[l + 1][r] + a[l] * (n - len + 1), f[l][r - 1] + a[r] *(n - len + 1));
}
}
printf("%d\n", f[1][n]);
return 0;
}
HDU2859 Phalanx
思路
状态表示
f
[
i
]
[
j
]
f[i][j]
f[i][j]:所有以
i
,
j
i,j
i,j为左下角的对称子矩阵
属性:MAX
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1005;
char s[N][N];
int f[N][N];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
while(~scanf("%d", &n) && n) {
memset(s, 0, sizeof s);
memset(f, 0, sizeof f);
for(int i = 1; i <= n; i ++)
cin >> (s[i] + 1);
for(int i = 1; i <= n; i ++) {
f[i][n] = f[1][i] = 1;
}
int ans = 1;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++) {
if(i == 1 || j == n) continue;
int x = i, y = j;
while(x >= 1 && j <= n && s[x][j] == s[i][y]) x --, y ++;
int len = i - x;
if(len >= f[i - 1][j + 1] + 1)
f[i][j] = f[i - 1][j + 1] + 1;
else
f[i][j] = len;
ans = max(ans, f[i][j]);
}
cout << ans << endl;
}
return 0;
}
POJ3616Milking Time
思路
状态表示
f
[
i
]
f[i]
f[i]: 考虑前
i
i
i个区间的所有选法
属性:
m
a
x
max
max
状态计算:
f
[
i
]
=
m
a
x
(
f
[
i
]
,
f
[
j
]
+
p
[
i
]
.
w
)
,
w
h
e
n
p
[
j
]
.
r
+
R
<
=
p
[
i
]
.
l
f[i] = max(f[i], f[j] + p[i].w) ,\ \ when \ \ p[j].r + R <= p[i].l
f[i]=max(f[i],f[j]+p[i].w), when p[j].r+R<=p[i].l
代码
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int f[N];
int n, m, R;
struct node {
int l, r, w;
}p[N];
bool cmp(node a, node b) {
return a.l < b.l;
}
int main() {
while(~scanf("%d%d%d", &n, &m, &R)) {
memset(f, 0, sizeof f);
int cnt = 0;
for(int i = 0; i < m; i ++) {
int l, r, w;
scanf("%d%d%d", &l, &r, &w);
p[cnt].l = l, p[cnt].r = r, p[cnt].w = w, cnt ++;
}
sort(p, p + cnt, cmp);
int ans = 0;
for(int i = 0; i < m; i ++){
f[i] = p[i].w;
for(int j = 0; j < i; j ++){
if(p[j].r + R <= p[i].l)
f[i] = max(f[i], f[j] + p[i].w);
}
ans = max(ans, f[i]);
}
printf("%d\n", ans);
}
return 0;
}