BZOJ 1133 [POI2009]Kon

来源:互联网 发布:淘宝十大黑店 编辑:程序博客网 时间:2024/05/16 14:15

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


【题目分析】
动态规划。


【代码】

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int dp[51][601],ans[601][601];int n,a[601][601],outi,outj,outmax=-0x3f3f3f3f;int pre[601][601];int out[51];int main(){    int n,k;scanf("%d%d",&n,&k);    for (int i=1;i<n;++i)        for (int j=i+1;j<=n;++j)        {            scanf("%d",&a[i][j]);            a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];        }//  for (int i=0;i<=n;++i)//  {//      for (int j=0;j<=n;++j)//          printf("%4d",a[i][j]);//      printf("\n");//  }    for (int i=0;i<n;++i)        for (int j=i+1;j<=n;++j)            if (i==0) ans[i][j]=a[j][n]-a[j][j];            else ans[i][j]=a[j][n]-a[i][n]-a[j][j]+a[i][j];//  for (int i=0;i<=n;++i)//  {//      for (int j=0;j<=n;++j)//          printf("%d ",ans[i][j]);//      printf("\n");//  }    memset(dp,-0x3f,sizeof dp);//  printf("%d\n",dp[0][0]);    dp[0][0]=1;    for (int i=1;i<=k;++i)        for (int j=1;j<n;++j)            for (int l=0;l<j;++l)            {                if (dp[i-1][l]+ans[l][j]>dp[i][j])                {                    dp[i][j]=max(dp[i][j],dp[i-1][l]+ans[l][j]);                    pre[i][j]=l;                }                else if (dp[i-1][l]+ans[l][j]==dp[i][j]&&l<=pre[i][j])                    pre[i][j]=l;                if (dp[i][j]>outmax||i>outi)                {                    outmax=dp[i][j];                    outi=i;                    outj=j;                }            }    int top=outi;    while (outi)    {        out[outi]=outj;        outj=pre[outi][outj];        outi--;    }    for (int i=1;i<=top;++i) printf("%d%c",out[i],i==top?'\n':' ');//  printf("out i= %d out j=%d  max is  %d\n",outi,outj,outmax);}
0 0