Pangu and Stones
题意:现有n堆石子,每次合并k堆石子,L<=k<=R,每次合并石子花费代价是合并的石子的总数量;问最后能否合并成一堆石子,若能,输出最小代价;反之输出0;
思路:令dp[i][j][k]表示将区间[i, j]合并成k堆所花费最小代价;
当k=1时,dp[i][j][1]=min(dp[i][i+x][k-1]+dp[i+x+1][j][1]+sum[i][j] | i<=x<=j, L<=k<=R);
当k>=2时, dp[i][j][k]=min(dp[i][i+x][k-1]+dp[i+x+1][j][1] | i<=x<=j);
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int sum[110][110], dp[110][110][110], a[110];
int main(){
int N, L, R;
while(~scanf("%d%d%d", &N, &L, &R)){
memset(dp, INF, sizeof(dp));
for(int i=1; i<=N; i++){
scanf("%d", &a[i]);
}
for(int i=1; i<=N; i++){
sum[i][i-1]=0;
for(int j=i; j<=N; j++){
sum[i][j]=sum[i][j-1]+a[j];
dp[i][j][j-i+1]=0;
}
}
for(int d=1; d<=N; d++){
for(int i=1; i+d<=N; i++){
for(int j=i; j<i+d; j++){
for(int k=L-1; k<=R-1; k++){
dp[i][i+d][1]=min(dp[i][i+d][1], dp[i][j][k]+dp[j+1][i+d][1]+sum[i][i+d]);
}
}
for(int k=2; k<=d; k++){
for(int j=i; j<i+d; j++){
dp[i][i+d][k]=min(dp[i][i+d][k], dp[i][j][k-1]+dp[j+1][i+d][1]);
}
}
}
}
if(dp[1][N][1]==INF) printf("0\n");
else printf("%d\n", dp[1][N][1]);
}
return 0;
}