DP学习笔记

本文解析了两道NOIP竞赛题目:1999年的导弹拦截问题及2004年的合唱队形问题。通过代码实现介绍了如何使用动态规划解决最长递增子序列和最长非降子序列的问题。

1.NOIP 1999 导弹拦截

一开始在tyvj上交,但是就是尼玛一直不过,数组开大,用unsigned long,用文件读入输出,尼玛不是Runtime error 就是Wrong answer!

最后起火去rqnoj上交,改了下就过了。。。这周回去还是请教下别人到底是哪里出问题了吧

这道题藐视内涵是第二个问的证明,我是直接用的结论,下午抽空看看。。。那个什么定理好像看离散数学 二元关系的时候看到了。。只是那时候期末,后面就没看了!

#include<stdio.h>
#define MAXN 1000
int main(void)
{
FILE *f1, *f2;
f1 = fopen("1209.in", "rb");
f2 = fopen("1209.out", "wb");
int opt1[MAXN], opt2[MAXN], max1 = 1, max2 = 1, maxn1 = 1, maxn2 = 1;
unsigned long num[MAXN];
int i = 0, j;
fscanf(f1, "%lu", &num[0]);
opt1[0] = opt2[0] = 1;
while(fscanf(f1, ",%lu", &num[(i++)+1]) != EOF)
{
max1 = max2 = 0;
for(j = 0; j < i; j++)
{
if(num[j] > num[i] && opt1[j] > max1) max1 = opt1[j];
if(num[j] <= num[i] && opt2[j] > max2) max2 = opt2[j];
}
opt1[i] = max1+1; opt2[i] = max2 +1;
maxn1 = maxn1 < opt1[i]? opt1[i]: maxn1;
maxn2 = maxn2 < opt2[i]? opt2[i]: maxn2;
}
fprintf(f2, "%d,%d\n", maxn1, maxn2-1);
fclose(f1);
fclose(f2);
return 0;
}

 

2.NOIP 2004 合唱队形

DP两次吧。。但是没想通自己一开始把 第二次逆序求最长非升子序列 转换为求最长非降子序列错了! 难道是< 逆命题 >=? 周末研究

#include<stdio.h>
int main(void)
{
freopen("26.in", "r", stdin);
int n, high[250], opt1[250], opt2[259];
int i, j, max1, max2, maxn = 1;
opt1[1] = opt2[1] = 1;
scanf("%d", &n);
for(i = 1; i <= n; i++) scanf("%d", &high[i]);
for(i = 1; i <= n; i++)
{
max1 = 0;
for(j = 1; j < i; j++)
if(high[j] < high[i] && opt1[j] > max1) max1 = opt1[j];
opt1[i] = max1+1;
}
for(i = n; i > 0; i--)
{
max2 = 0;
for(j = n; j > i; j--)
if(high[j] < high[i] && opt2[j] > max2) max2 = opt2[j];
opt2[i] = max2+1;
}
for(i = 1; i <= n; i++)
if(opt1[i]+opt2[i]-1 > maxn) maxn = opt1[i]+opt2[i]-1;
printf("%d\n", n-maxn);
return 0;
}



转载于:https://www.cnblogs.com/shixuehunk/archive/2011/10/12/2208543.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值