You Are the One HDU - 4283
考察:区间dp
转移方程没想出来,思路参考大佬们的题解
错误思路:
本题主要难在[i,j]区间取走某一个数k时,我们要考虑继续往后取还是往前取,如果取前面的就只能取尾端,这就与我们一开始的子结构不符.所以此思路设置间断点划分集合行不通.
正确思路:
f[i,]表示i~j人走花费的时间.考虑将区间[i,j]看成一个栈,如果已知栈底i是第k个走的,那么[i+1,i+k-1]必须在他之前走,而这个区间又是符合我们确定的子结构的.那么后半部分[i+k,j]必须先等(sum[j]-sum[i+k-1])*k后,又可以看成一个栈.这也是符合我们划分的子结构的.
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 const int N = 110; 7 int a[N],f[N][N],sum[N]; 8 int main() 9 { 10 int T,kcase = 0; 11 scanf("%d",&T); 12 while(T--) 13 { 14 int n; memset(f,0,sizeof f); 15 scanf("%d",&n); 16 for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i]; 17 for(int len=2;len<=n;len++) 18 for(int l=1;l+len-1<=n;l++) 19 { 20 int r = l+len-1; f[l][r] = 0x3f3f3f3f; 21 for(int k=1;k<=r-l+1;k++) 22 f[l][r] = min(a[l]*(k-1)+f[l+1][l+k-1]+f[l+k][r]+(sum[r]-sum[l+k-1])*k,f[l][r]); 23 } 24 printf("Case #%d: %d\n",++kcase,f[1][n]); 25 } 26 return 0; 27 }
2021.3.17 二刷,真的完全想不到...这道题是求最优出栈过程.第二次看这题反应是这也能区间dp ,不能以k是第1个走的划分集合,因为f[l][k-1]已经不是与f[l][r]的相同子结构了.这道题以栈底是第k个走的,更小的区间子结构与i,j相同.