tyvj MM不哭
这道题是一个典型的区间类动态规划,与之类似的还有rqnoj的关灯问题~
这种题目的解法通常比较单一,但是比较难想出正确的解法,下面就是我的解法:
假设此时已经安慰好了第i个MM和第j个MM及其之间的所有MM。如果此时站在第i个MM所在的位置,用f[i,j,0]表示之后需要消耗的最小RP;如果此时站在第j个MM所在的位置,用f[i,j,1]表示在此之后需要消耗的最小RP。
这里通过记忆化搜索实现
下面附上核心代码
#include <cstdio> #include <cstdlib> #include <cstring> #define zsz 200000000//注意最大值不要定小了,我刚开始定了100000000,结果有一组数据的最小值是110036500,WA了一次~~悲剧 int n; int f[1005][1005][2]; int w[1005],sum[1005],l[1005]; int min(int a,int b) { return (a>b)?b:a; } int minn(int a,int b,int k) { if (a==0&&b==n) return 0; if (f[a][b][k]!=-1) return f[a][b][k]; f[a][b][k]=zsz; if (k==0) { if (a-1>=0) f[a][b][k]=min(f[a][b][k],minn(a-1,b,0)+(l[a]-l[a-1])*(sum[n]-sum[b]+sum[a-1])); if (b+1<=n) f[a][b][k]=min(f[a][b][k],minn(a,b+1,1)+(l[b+1]-l[a])*(sum[a-1]+sum[n]-sum[b])); } if (k==1) { if (a-1>=0) f[a][b][k]=min(f[a][b][k],minn(a-1,b,0)+(l[b]-l[a-1])*(sum[n]-sum[b]+sum[a-1])); if (b+1<=n) f[a][b][k]=min(f[a][b][k],minn(a,b+1,1)+(l[b+1]-l[b])*(sum[n]-sum[b]+sum[a-1])); } return f[a][b][k]; } int main() { freopen("zsz.in","r",stdin); freopen("zsz.out","w",stdout); int v; scanf("%d",&n); scanf("%d",&v); for (int i=1;i<=n;i++) { scanf("%d%d",&l[i],&w[i]); sum[i]=sum[i-1]+w[i]; } memset(f,-1,sizeof(f));//刚刚知道memset可以直接附上-1.. printf("%d\n",minn(v,v,0)); return 0; }