题意
在每一组测试中,第一行给你两个数n,k,第二行给你一个大小为n的数组要求你可以删一些数,至少有k个能满足,a[i]=i,请问删除的数最少有几个,如果没有这样的数字,输出-1
思路
这道题其实很容易能看出来这是一个dp,但是我们应该怎么分析呢?
首先对于dp[i][j]代表前i个数,删除第j个了以后有几个满足这样的情况。
1.我们这个点不删
i
f
(
a
[
i
]
=
=
i
−
j
)
if(a[i]==i-j)
if(a[i]==i−j)
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
]
+
1
dp[i][j]=dp[i-1][j]+1
dp[i][j]=dp[i−1][j]+1
e
l
s
e
else
else
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
]
dp[i][j]=dp[i-1][j]
dp[i][j]=dp[i−1][j]
2.这个点删除
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
1
]
[
j
−
1
]
,
d
p
[
i
−
1
]
[
j
]
+
(
a
[
i
]
=
=
i
−
j
)
)
dp[i][j]=max(dp[i-1][j-1],dp[i-1][j]+(a[i]==i-j))
dp[i][j]=max(dp[i−1][j−1],dp[i−1][j]+(a[i]==i−j))
#include<iostream>
#include<cstring>
using namespace std;
int dp[3000][3000];
int a[2102100];
int k;
int query(int n){
for(int i=0;i<=n;i++){
for(int j=1;j<=n;j++){
if(dp[j][i]>=k)
return i;
}
}
return -1;
}
int main(){
int T;
cin>>T;
while(T--){
int n;
cin>>n>>k;
memset(dp,0,sizeof dp);
for(int i=1;i<=n;i++)cin>>a[i];
if(a[1]==1)dp[1][0]=1;
else dp[1][0]=0;
dp[1][1]=0;
for(int i=2;i<=n;i++){
for(int j=0;j<=i;j++){//删除了第几次
if(j==0)
if(a[i]==i-j){
dp[i][j]=1+dp[i-1][j];
}else dp[i][j]=dp[i-1][j];
else
dp[i][j]=max((a[i]==i-j)+dp[i-1][j],dp[i-1][j-1]);
}
}
int ans=query(n);
cout<<ans<<endl;
}
}