| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
阴险题,63ms的dp,有一点很坑。。。首先看题第一反应肯定是DP的。。。然后关键是得到最小值之后回溯答案不能按照dp的时候记录的来。。。(其实我的代妈中间trc那个数组是废的),比如下面这个数据:
23333 2333 233 233 2333
答案应该是23333/2333/233,233,2333而不是直接dp回溯得到的23333/2333,233/233,2333
因为有了23333之后后面的部分最大值是2333+233还是2333+2*233已经不重要了。。。一句话就是,DP得到的结果,只能保证正确的极值,不一定是正确组合。。。
#include <iostream>
#include <stdio.h>
using namespace std;
int mx[505][505], trc[505][505], psum[505], page[505];
int m,k;
int MX(int a, int b){
return (a>b)?a:b;
}
int MN(int a, int b){
return (a<b)?a:b;
}
int main() {
int n;
scanf("%d",&n);
for(int ii = 0; ii < n; ii++){
scanf("%d%d",&m,&k);
for(int i = 1; i <= m; i++){
scanf("%d", &page[i]);
}
psum[0] = 0;
for(int i = 1; i <= m; i++){
psum[i] = psum[i-1] + page[i];
}
mx[m][0] = 0;
for(int i = m-1; i >= 0; i--){
int jstart = MX(k-i,1), jend = MN(m-i,k);
for(int j = jstart; j <= jend; j++){
int arg = -1, mn = 2147483647;
int tstart = MX(k-j+1,i+1), tend = MN(m,m-j+1);
if(j == 1) tstart = tend;
for(int t = tstart; t <= tend; t++){
if(psum[t]-psum[i] >= mn) break;
int thisMn = MX(psum[t]-psum[i], mx[t][j-1]);
if(thisMn < mn){
mn = thisMn;
arg = t;
}
}
mx[i][j] = mn;
trc[i][j] = arg;
}
}
int ren = k, val = mx[0][k], pos = 0;
while(ren > 0){
int sstart = pos+1, send = m-ren+1;
if(ren==1) sstart = send;
for(int s = sstart; s <= send; s++){
if(mx[s][ren-1] <= val){
for(int q = pos; q < s; q++){
printf("%d ", page[q+1]);
}
if(ren != 1) printf("/ ");
pos = s;
ren--;
break;
}
}
}
printf("\n");
}
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator