Solution - P4267
\(\color{3498DB}\text{P4267 [USACO18FEB] Taming the Herd G}\)
设 \(f_{i,j}\) 表示前 \(i\) 天操作了 \(j\) 次原序列最小的修改次数。
定义 \(d_{i,j}\) 表示从第 \(i\) 天开始出逃到第 \(j\) 天时原序列的修改次数,则有
\[d_{i,j}=d_{i,j-1}+[a_j \not= j-i]\\
f_{i,j}=\min^{i-1}_{k=1}\min^n_{j=1}\{f_{k,j-1}+d_{k+1,i}\}
\]
对于操作 \(i\) 次的答案即为 \(f_{n,i}\)。
时间复杂度 \(O(n^3)\)。
#include<cstdio>
#include<cstring>
const int N=110;
int n;
int a[N];
int d[N][N];
int f[N][N];
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9')ch=='-'?f=0:0,ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f?x:-x;
}
inline int min(int a,int b){return a<b?a:b;}
int main(){
n=read();
for(int i=1;i<=n;++i)
a[i]=read();
for(int i=0;i<=n;++i)for(int j=i;j<=n;++j)
d[i][j]=d[i][j-1]+(a[j]!=j-i);
memset(f,0x3f,sizeof(f)),f[0][0]=0;
for(int i=0;i<n;++i)for(int j=1;j<=n;++j)for(int k=i+1;k<=n;++k)
f[k][j]=min(f[k][j],f[i][j-1]+d[i+1][k]);
for(int i=1;i<=n;++i)
printf("%d\n",f[n][i]);
return 0;
}
浙公网安备 33010602011771号