洛谷 P5424 [USACO19OPEN]Snakes G

传送门

我自关山点酒,千秋皆入喉

题目描述:略

思路:这个东西明显就是一个区间的dp,f[i][j]代表抓到第i条蛇,用了j次修改的最优值。(这个题有个坑啊,观察样例可以发现第一次调整网的大小是不算在k次操作里面的呜呜呜。)
下面考虑怎么转移:我们设g[i][j]代表只用一张网抓[i][j]的蛇所花费的空间,然后就可以很容易的写出状态转移方程:
f[i][j]=min(f[i][j],f[t][j-1]+g[t+1][i])
之后就过了QWQ
(这题为什么是蓝题)

#include 
#include 
#include 
#include 
#define int long long 
using namespace std;
const int maxn=405;
int n,m,f[maxn][maxn];//f[i][j]代表到i条蛇,用了j次魔法的最优解 
int a[maxn],sum[maxn],g[maxn][maxn];//g[i][j]代表第i个蛇到第j个蛇用一只网 
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
main(){
    n=read();m=read();
    sum[0]=0;
    m++;
    for(int i=0;i<=n;i++){
    	for(int j=0;j<=m;j++){
    		f[i][j]=1e9+7; 
		}
	}
    f[0][0]=0;
    for(int i=1;i<=n;i++) a[i]=read(),sum[i]=sum[i-1]+a[i];
    for(int i=1;i<=n;i++){
    	int maxn=0;
    	for(int j=i;j<=n;j++){
    		maxn=max(maxn,a[j]);
		    g[i][j]=maxn*(j-i+1)-sum[j]+sum[i-1];//一网打尽么么哒 
		}
	}
	for (int k=1;k<=m;++k)
		for (int i=1;i<=n;++i)
			for (int j=0;j<=i;++j)
				f[i][k]=min(f[i][k],f[j][k-1]+g[j+1][i]);
	printf("%lld",f[n][m]);
    return 0; 
} 

//f[i][j]=min(f[i][j],f[t][j-1]+g[t+1][i]) 

你可能感兴趣的:(dp)