Time Limit: 3000MS | Memory Limit: 10000K | |
Total Submissions: 7620 | Accepted: 2405 |
Description
Input
Output
Sample Input
2 9 3 100 200 300 400 500 600 700 800 900 5 4 100 100 100 100 100
Sample Output
100 200 300 400 500 / 600 700 / 800 900 100 / 100 / 100 / 100 100
Source
dp[i][j]表示第i个往后的所有数分成j部分的每部分和的最小值。
注意最后答案要使得斜杠尽量往前摆,需要进行一个调整,从前往后看每个斜杠,如果该斜杠往前移动一位,对后面的数进行划分的结果小于整体最优解,则斜杠可以向前移动一位。
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 1010
#define ll long long
ll val[N], sum[N];
ll dp[N][N];
int fa[N][N], pos[N];
int main()
{
//freopen("C:\\Users\\zfh\\Desktop\\in.txt", "r", stdin);
//freopen("C:\\Users\\zfh\\Desktop\\out.txt", "w", stdout);
int t; scanf("%d", &t);
while(t--)
{
int n, m;
scanf("%d%d", &n, &m);
sum[0] = 0;
for(int i = 1; i <= n; i++)
{
scanf("%I64d", &val[i]);
sum[i] = sum[i-1]+val[i];
}
for(int i = 1; i <= n; i++)
dp[i][1] = sum[n]-sum[i-1];
for(int i = 2; i <= m; i++)
{
for(int j = 1; j <= n && n-j+1 >= i; j++)
{
dp[j][i] = max(dp[j+1][i-1], val[j]);
fa[j][i] = j;
for(int k = j+1; k <= n && n-k >= i-1; k++)
{
if(dp[j][i] > max(sum[k]-sum[j-1], dp[k+1][i-1]))
{
dp[j][i] = max(sum[k]-sum[j-1], dp[k+1][i-1]);
fa[j][i] = k;
}
}
}
}
//printf("dp: %I64d\n", dp[1][m]);
int p = 1, maxv = dp[1][m];
for(int i = 1; i <= m-1; i++)
{
pos[i] = fa[p][m-i+1];
p = fa[p][m-i+1]+1;
}
pos[m] = n;
for(int i = 1; i <= m-1; i++)
{
while(pos[i]-1 > pos[i-1] && dp[pos[i]][m-i] <= maxv)
pos[i]--;
}
p = 1;
for(int i = 1; i <= n; i++)
{
if(i != 1) printf(" ");
printf("%I64d", val[i]);
if(i == pos[p] && p != m)
{
printf(" /");
p++;
}
}
printf("\n");
}
return 0;
}