【bzoj1133】[POI2009]Kon

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 10007
using 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值