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;
}