题目链接:点击打开链接
题目描述:- =,第一遍因为英语渣看错题意我会乱说?。。嘛,总之题意就是让几个士兵出列,剩下的士兵都可以看到左侧或者右侧的无穷远处(身高构成一个三角形的构型)。如图。
题目坑点:注意!我被坑了好几次!(泪目)。中间最高的两位是允许酱紫的,但是如果不是中间的那两个大高个,剩下的人就必须严格单调递增或递减。这里我看到的另一个博客,写的不错:(但是注意:他给的sample的输出是错的,在他博客评论里是正确的)→点击打开链接
解题思路:dp1【i】表示从左往右到这一点能构成的最长升序子串的长度,dp1【i】等于之前所有比【i】矮的人里dp1最大的加一,差不多原理再从右往左找一遍dp2,表示从右往左能构成的最长升序子串——也就是从左往右的最长降序子串。好了,(dp1【i】+dp2【i】-1)就可以表示这点能”发出去的“最长的三角形,然后就知道答案咯~
AC代码:
好吧。。别吐槽那个solve1和solve2了。就是写渣了而已嘛。然后为了避免那个坑点。。我把代码改的更加渣了
- =(泪、、)
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
double arr[1050],dp1[1050],dp2[1050],temp[1050];
int N;
void solve1(double dp[1050])
{
int i,j,cc,flag;
dp[0]=1;
for(i=1;i<N;i++)
{
cc=-1;
flag=0;
for(j=0;j<i;j++)
{
if(arr[i]>arr[j])
{temp[++cc]=dp[j];flag=1;}
}
if(flag)
{
int maximum=temp[0];
for(j=0;j<=cc;j++)
if(maximum<temp[j])
maximum=temp[j];
dp[i]=maximum+1;
}
else
{
dp[i]=1;
}
}
}
void solve2(double dp[1050])
{
int i,j,cc,flag;
dp[N-1]=1;
for(i=N-2;i>=0;i--)
{
cc=-1;
flag=0;
for(j=N-1;j>i;j--)
{
if(arr[i]>arr[j])
{temp[++cc]=dp[j];flag=1;}
}
if(flag)
{
int maximum=temp[0];
for(j=0;j<=cc;j++)
if(maximum<temp[j])
maximum=temp[j];
dp[i]=maximum+1;
}
else
{
dp[i]=1;
}
}
}
int ok(int maximum,int nimas)
{
int i;
for(i=nimas+1;i<N;i++)
{
if(dp1[i]+dp2[i]==maximum&&arr[i]==arr[nimas])
return 1;
}
return 0;
}
int main()
{
//freopen("alignment_input.txt","r",stdin);
cin>>N;
int i;
for(i=0;i<N;i++)
scanf("%lf",&arr[i]);
solve1(dp1);
solve2(dp2);
/*
for(i=0;i<N;i++)
cout<<dp1[i]<<" ";
cout<<endl;
for(i=0;i<N;i++)
cout<<dp2[i]<<" ";
cout<<endl;
*/
int nimas=0;
int maximum=dp1[0]+dp2[0];
for(i=1;i<N;i++)
{
if(maximum<dp1[i]+dp2[i])
{maximum=dp1[i]+dp2[i];nimas=i;}
}
if(ok(maximum,nimas))
cout<<N-maximum<<endl;
else
cout<<N-maximum+1<<endl;
return 0;
}