【bzoj1133】[POI2009]Kon

来源:互联网 发布:淘宝卖家页面生成器 编辑:程序博客网 时间:2024/05/17 08:38

Description

火车沿途有N个车站,告诉你从每一站到每一站的人数,现在查票员只能查K次票,每次查票可以控制目前在车上的所有乘客的车票。求一个查票方案,使得控制的不同的乘客尽量多。 (显然对同一个乘客查票多次是没有意义的,只算一次)

Input

第一行正整数 N K (1≤K<N≤600, K≤50). 接下来N-1行,第i行第j个数描述第i站上,到第i+j站下的乘客个数。总乘客数≤2*10^9

Output

单调增的K个整数,用空格隔开,表示经过哪些站以后查票。

Sample Input

7 2

2 1 8 2 1 0

3 5 1 0 1

3 1 2 2

3 5 6

3 2

1
Sample Output

2 5

题解
f[i][j]表示在i-i+1站间查票,能查到的最大人数,转移枚举前一个查票点,计算新增加的人数(类似于求矩形面积),跟新方案即可。

代码

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<map>#define mod 10007using namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int n,k,ans,pos;int a[605][605],f[605][55],from[605][55],step[55];int main(){    n=read();k=read();    for (int i=1;i<n;i++)        for (int j=i+1;j<=n;j++)            a[i][j]=read();    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)            a[i][j]+=a[i-1][j];    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)            a[i][j]+=a[i][j-1];    memset(f,0x80,sizeof(f));     f[0][0]=0;    for (int i=1;i<=n;i++)        for (int j=1;j<=k;j++)            for (int l=0;l<i;l++)            {                int tmp=a[i][n]-a[i][i]-a[l][n]+a[l][i];                if (f[i][j]<f[l][j-1]+tmp)                {                    f[i][j]=f[l][j-1]+tmp;                    from[i][j]=l;                }                if (j==k&&ans<f[i][j])                {                    ans=f[i][j];                    pos=i;                }            }    int stp=0;    for (int i=pos;i;i=from[i][k],k--)    {        stp++;        step[k]=i;    }    for (int i=1;i<stp;i++)printf("%d ",step[i]);    cout<<step[stp];    return 0;}