2014.10.13
继续复习!!!
从今天起要复习动态规划,预计会复习很长时间。
今天复习了一道题,也是我动态规划的开篇题,《导弹拦截》。
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭,由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹的枚数和导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数,每个数据之间有一个空格),计算这套系统最多能拦截多少导弹?如果要拦截所有导弹最少要配备多少套这种导弹拦截系统?
输入格式 Input Format
第一行数字n表示n个导弹(n<=200)
第二行n个数字,表示n个导弹的高度
输出格式 Output Format
一个整数,表示最多能拦截的导弹数
一个整数,表示要拦截所有导弹最少要配备的系统数
样例输入:
8
389 207 155 300 299 170 158 65
样例输出:
6
2
第一问:最长不上升子序列。
第二问:可以用贪心法,还可以通过证明得出求最长上升子序列。这个方法的证明非常复杂,目测了一下还用到了偏序集什么的没听说过,回头看看。
代码如下:
#include
#include
#include
#include
#include
using namespace std;
int N,a[210],b[210],f[210],maxx=-10000000;
int main()
{
scanf("%d",&N);
for(int i=1;i<=N;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
f[1]=1;
for(int i=2;i<=N;i++)
{
for(int j=1;jf[i]) f[i]=f[j];
f[i]++;
}
for(int i=1;i<=N;i++)
if(maxxb[j]&&f[j]>f[i]) f[i]=f[j];
f[i]++;
}
for(int i=1;i<=N;i++)
if(maxx
今天就到这里。。。
14号没空,没复习。
2014.10.15
今天复习了两道做过的DP,都是基本DP,没什么难度。
第一道:《苹果》
描述 Description
农场的夏季是收获的好季节。在Farmer John的农场,他们用一种特别的方式来收小苹果:Bessie摇小苹果树,小苹果落下,然后Farmer John尽力接到尽可能多的小苹果。
作为一个有经验的农夫,Farmer John将这个过程坐标化。他清楚地知道什么时候(1<=t<=1,000,000)什么位置(用二维坐标表示,-1000<=x,y<=1000)会有小苹果落下。他只有提前到达那个位置,才能接到那个位置掉下的小苹果。
一个单位时间,Farmer John能走s(1<=s<=1000)个单位。假设他开始时(t=0)站在(0,0)点,他最多能接到多少个小苹果?
Farmer John 在接小苹果时,从某个点到另外一点按照直线来走。
输入格式 Input Format
第一行:N(小苹果个数)和S(速度)
第2..N+1行:每行三个数Xi,Yi,Ti,表示每个小苹果掉下的位置和落下的时间。
输出格式 Output Format
仅一行,一个数,表示最多能接到几个小苹果
样例输入 Sample Input
5 3
0 0 1
0 3 2
-5 12 6
-1 0 3
-1 1 2
样例输出 Sample Output
3
时间限制 Time Limitation
1s
注释 Hint
n<=5000
不难,代码如下:
#include
#include
#include
#include
#include
using namespace std;
int N,S,f[5010],ans=0;
struct apple
{
int x,y,t;
}d[5010];
bool cmp(apple aa,apple bb)
{
return aa.t=0&&((d[i].t-d[j].t)*S>=lyd(i,j)))
f[i]=max(f[i],f[j]+1);
ans=max(ans,f[i]);
}
printf("%d\n",ans);
}
int main()
{
init();
DP();
return 0;
}
第二道:《轮船问题》
描述 Description
某国家被一条河划分为南北两部分,在南岸和北岸总共有N对城市,每一城市在对岸都有一个城市作为友好城市。每一对友好城市都希望有一条航线来往,于是他们向政府提出了申请。由于河终年有雾。政府决定允许开通的航线就互不交叉(如果两条航线交叉,将有很大机会撞船)。兴建哪些航线以使在安全条件下有最多航线可以被开通。
输入格式 Input Format
第一行两个由空格分隔的整数x,y,10〈=x,y〈=60000,x,y中较长的表示河的长度另一个表示宽。第二行是一个整数N(1<=N<=5000),表示分布在河两岸的城市对数。接下来的N行每行有两个由空格分隔的正数C,D(C、D〈=x〉,描述每一对友好城市与河起点的距离,C表示北岸城市的距离而D表示南岸城市的距离。在河的同一边,任何两个城市的位置都是不同的。
输出格式 Output Format
一个整数,表示安全条件下能够开通的最大航线数目。
样例输入 Sample Input
30 4
5
4 5
2 4
5 2
1 3
3 1
样例输出 Sample Output
3
时间限制 Time Limitation
1s
来源 Source
ceoi经典问题
算法:左边从大到小排序,右边做最长下降子序列即可,其他排序方式均可。
代码如下:
#include
#include
#include
#include
#include
using namespace std;
int x,y,N,f[5010],ans=-10000;
struct line
{
int le,ri;
}d[5010];
bool cmp(line aa,line bb)
{
return aa.le>bb.le;
}
void init()
{
memset(f,0,sizeof(f));
scanf("%d%d%d",&x,&y,&N);
for(int i=1;i<=N;i++) scanf("%d%d",&d[i].le,&d[i].ri);
sort(d+1,d+N+1,cmp);
}
void DP()
{
f[1]=1;
for(int i=2;i<=N;i++)
{
for(int j=1;jd[i].ri&&f[i]
今天的两道题难度不大,明天开始加大难度并且复习多种DP。