这个题有点意思,一开始没想到用dp,没啥思路,后来看题解才恍然大悟:k才1~100,直接枚举每个-1点的k取值进行dp就行了。先预处理出来sz[i][j] i左边的比j大的数,lz[i][j] i右边比j小的数。然后就没啥了。
题干:
Description
Input
Output
Sample Input
5 4 4 2 -1 -1 3
Sample Output
4
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF =
1 <<
30;
typedef long long ll;
typedef double db;
template <
class T>
void read(T &
x)
{
char c;
bool op =
0;
while(c = getchar(), c <
'0' || c >
'9')
if(c ==
'-') op =
1;
x = c -
'0';
while(c = getchar(), c >=
'0' && c <=
'9')
x = x *
10 + c -
'0';
if(op) x = -
x;
}
template <
class T>
void write(T x)
{
if(x <
0) putchar(
'-'), x = -
x;
if(x >=
10) write(x /
10);
putchar('0' + x %
10);
}
int n,m,tot =
0;
int a[
10020],num[
10020];
int lz[
10050][
105];
int sz[
10020][
105];
int dp[
10020][
105];
int k;
int main()
{
read(n);read(k);
duke(i,1,n)
{
read(a[i]);
if(a[i] == -
1)
num[++tot] =
i;
}
duke(i,1,n)
{
duke(j,1,k)
{
if(a[i -
1] >
j)
sz[i][j] = sz[i -
1][j] +
1;
else
sz[i][j] = sz[i -
1][j];
}
}
lv(i,n -
1,
1)
{
duke(j,1,k)
{
if(a[i +
1] < j && a[i +
1] != -
1)
lz[i][j] = lz[i +
1][j] +
1;
else
lz[i][j] = lz[i +
1][j];
}
}
duke(i,1,n)
{
duke(j,1,k)
{
if(a[i] != -
1)
{
dp[i][j] = dp[i -
1][j];
continue;
}
else
{
dp[i][j] =
INF;
duke(l,1,k)
{
dp[i][j] = min(dp[i -
1][l] + lz[i][j] +
sz[i][j],dp[i][j]);
}
}
}
}
int ans =
INF;
duke(i,1,k)
{
ans =
min(ans,dp[n][i]);
}
duke(i,1,n)
{
if(a[i] != -
1)
{
ans +=
sz[i][a[i]];
}
}
printf("%d\n",ans);
return 0;
}
/*
5 4
4 2 -1 -1 3
*/
转载于:https://www.cnblogs.com/DukeLv/p/9525359.html
相关资源:数据结构—成绩单生成器