P1091 [NOIP2004 提高组] 合唱队形
Part1:链接:
Part2:题目
Part3:思路
隔了这么久,屑人再次捡起了他的节操,洗了洗,然后开始续写他的苦逼dp之路了。
这道题我们可以用 LIS (Longest Increasing Subsequence,最长上升子序列) 来处理。
LIS代码:
///O(n^2)
///lis1[i]:当考虑前i个元素后能够产生的最长子序列的长度
for(int i=1; i<=n; i++)
{
lis1[i]=1;
for(int j=1; j<i; j++)
if(a[i]>a[j]) lis1[i]=max(lis1[i],lis1[j]+1);
///如果i位置上的数字大于j位置上的数字,此时要考虑
///加入对方的序列,还是保持自己的序列
}
我们从前到后求LIS,然后再由后至前求一遍LIS,将两个结果分别存储在两个不同的数组。
最后枚举中心位置,即如果以pos为中心,往左递减,往右递增,那么最多会有 (lis1[pos]+lis2[pos]-1) 个人。
减一的理由:lis1[pos]和lis2[pos]都会把pos位置的人列入考虑范围,所以减去重复的1。
最后让久违的「伊丽莎白」君为我们呈上代码。
Part4:AC代码
#include<iostream>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int a[105];
int lis1[105],lis2[105];
int main()
{
int n;
ios::sync_with_stdio(false);
cin>>n;
int ans=-1;
for(int i=1; i<=n; i++) cin>>a[i];
///第一遍LIS,正序
for(int i=1;i<=n;i++)
{
lis1[i]=1;
for(int j=1;j<i;j++)
if(a[i]>a[j]) lis1[i]=max(lis1[i],lis1[j]+1);
}
///第二遍LIS,逆序
for(int i=n;i>=1;i--)
{
lis2[i]=1;
for(int j=n;j>i;j--)
if(a[i]>a[j]) lis2[i]=max(lis2[i],lis2[j]+1);
}
for(int i=1;i<=n;i++) ans=max(ans,lis1[i]+lis2[i]-1);
///注意!!!!我们求得的是K,我们要的是n-k!!!
cout<<n-ans<<endl;
return 0;
}
今天是2021年6月7日,高考第一天。
鸡汤应该都喝饱了,我也说不出什么优美的语言。
那就祝愿各位活成自己的样子。
Part5:死宅时间!!!
取自《银魂——鬼道丸篇》
坂田银时:
有个器官比我的心脏还重要。虽然我看不见它,但是它确实在我的体内。
因为有它我才能站得直,就算步履蹒跚也能笔直往前走。
如果我不去的话,它可是会拦腰折断的, 我的灵魂它会拦腰折断的!比起心脏停止跳动,我更重视它!