P1020 导弹拦截(弱数据)
https://www.luogu.org/problem/show?pid=1020
法一,dp
第一问要求一个以第一个为起点最长不上升子序列。
第二问,只要后面的比前一个高,就要再另用一套系统,所以问题可以转化为求最长的上升子序列。
#include<iostream>
#include<cstdio>
#define LL long long
#define M 30010
using namespace std;
int a[111],n=0;
int d[111],f[111];
int main()
{
for(;scanf("%d",&a[++n])==1;)
{
d[n]=1;
}
d[0]=1;
for(int i=2;i<=n;i++)
{
int maxn=0;
for(int j=1;j<=i-1;j++)
if(a[j]>=a[i]&&maxn<d[j])
maxn=d[j];
d[i]+=maxn;
}
printf("%d\n",d[n]);
for(int i=0;i<=n;i++) d[i]=1;
for(int i=2;i<=n;i++)
{
int maxn=0;
for(int j=1;j<=i-1;j++)
if(a[j]<a[i]&&maxn<d[j])
maxn=d[j];
d[i]+=maxn;
}
int maxn=0;
for(int i=1;i<=n;i++)
{
maxn=max(maxn,d[i]);
}
printf("%d",maxn);
return 0;
}
法二、贪心
每次打炮弹时,都在已有系统中找一个满足条件的最低的系统,如果没有满足条件的,那么就需要加一套系统。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define LL long long
#define M 31000
using namespace std;
int a[111],n=0;
int d[111],h[111];
void dfs(int x,int m)
{
if(x==n+1)
{
printf("%d\n",m);
return;
}
int minn=M+1,minj;
for(int i=1;i<=m;i++)
{
if(h[i]>a[x]&&h[i]<minn)
minn=h[i],minj=i;
}
if(minn==M+1)
{
h[m+1]=a[x];
dfs(x+1,m+1);
}
else
{
h[minj]=a[x];
dfs(x+1,m);
}
return;
}
int main()
{
for(;scanf("%d",&a[++n])==1;)
{
d[n]=1;
}
d[0]=1;
for(int i=2;i<=n;i++)
{
int maxn=0;
for(int j=1;j<=i-1;j++)
if(a[j]>=a[i]&&maxn<d[j])
maxn=d[j];
d[i]+=maxn;
}
printf("%d\n",d[n]);
h[1]=M;
dfs(1,1);
return 0;
}