今天讲dp,这讲的不是一般的快。概念一句话,一道题10分钟带过。我基本上是挂机了一上午。之前老师极其慢的讲时候我都听的一脸懵逼,更不要说这么快的讲课了。今天上午讲了dp,各种背包。c组的越越都不知道01,完全背包怎么用。我懵逼了一上午,到刷题时还要看之前上课的PPT,在慢慢地理解一遍,还有之前集训前老师讲的课和PPT。看着别人的代码再理解一遍时才把题打出来。不会又不敢问老师因为我觉的我啥也不会。所以就、我今天刷的题很少。
第一题:有一种导弹拦截系统,这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。有导弹来袭只有一套系统,因此有可能不能拦截所有的导弹。输入导弹的枚数和导弹依次飞来的高度,计算这套系统最多能拦截多少导弹?如果要拦截所有导弹最少要配备多少套这种导弹拦截系统?这题也就是找最长不上升子序列。用dp写,转移方程是f[i]=max{f[j}+1(1<=j<i);
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,l1=0,l2=0;
int a[210],b[210]={},f[210]={};
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
f[1]=1;
for(int i=2;i<=n;i++)
{
for(int j=1;j<i;j++)
if(a[i]<=a[j]&&f[j]>f[i]) f[i]=f[j];
f[i]++;
}
for(int i=1;i<=n;i++)
if(f[i]>l1)
l1=f[i];
b[1]=1;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i;j++)
if(a[i]>a[j]&&b[i]<b[j]) b[i]=b[j];
b[i]++;
}
for(int i=1;i<=n;i++)
if(b[i]>l2)
l2=b[i];
cout<<l1<<endl<<l2<<endl;
}
第二题:N位同学站成一排,其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,则他们的身高满足T1<...Ti+1>…>TK(1<=i<=K)。已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。题目给出的a1<a2<a3<…<ai-1<ai>ai+1>…>an-1>an分解成两份,会得到a1<a2<a3<…<ai-1<ai与ai>ai+1>…>an-1>an.可以将原题转化为先找到一个点i,把原序列分成两组,在得到这两组中必须包括ai的一串正的lis以及一串倒的lis的长度相加在减一.即:ans=max{f1[j]+f2[j]}-1(1<=j<=n).再来看看我们原来的f数组,f[i]代表当前的lis长度,那么就是说我们用O(n^2)的效率算出了所有的lis.将lis正的求一遍得到f1数组,倒的再求一遍得到f2数组.枚举分割点i,找到最大的f1[i]+f2[i]-1,就是剩下的人数m.最少的人走掉意味这最多的人剩下,答案就是n-m.
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,maxn=0,l=0;
int a[110],f1[110]={},f2[110]={};
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
maxn=0;
for(int j=1;j<i;j++)
if(a[j]<a[i])
maxn=max(maxn,f1[j]);
f1[i]=maxn+1;
}
for(int i=n;i>=1;i--)
{
maxn=0;
for(int j=n;j>i;j--)
if(a[j]<a[i])
maxn=max(maxn,f2[j]);
f2[i]=maxn+1;
}
maxn=0;
for(int i=1;i<=n;i++)
maxn=max(maxn,f1[i]+f2[i]-1);
l=n-maxn;
cout<<l;
return 0;
}
第三题:河两岸总共有N对城市每一对有一条航线来往,开通的航线就互不交叉。兴建哪些航线以使在安全条件下有最多航线可以被开通。 先将一岸的城市排序,再比较到另一岸的路线有没有冲突,和计算。贪心思想,dp。
#include<bits/stdc++.h>
using namespace std;
struct o
{
int x,y;
}a[5100];
bool cmp(o g,o h)
{
return g.x<h.x;
}
int main()
{
int n,m,s,f[5100]={},l=0;
cin>>n>>m>>s;
for(int i=1;i<=s;i++)
cin>>a[i].x>>a[i].y;
sort(a+1,a+1+s,cmp);
for(int i=1;i<=s;i++)
{
l=0;
for(int j=1;j<i;j++)
if(a[j].y<a[i].y)
l=max(l,f[j]);
f[i]=l+1;
}
l=0;
for(int i=1;i<=s;i++)
l=max(l,f[i]);
cout<<l;
return 0;
}