zoukankan      html  css  js  c++  java
  • bzoj 1133: [POI2009]Kon dp

    1133: [POI2009]Kon

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 242  Solved: 81
    [Submit][Status][Discuss]

    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
     
      还是对这种字典序dp的实现方法非常不熟悉,以后看到字典序首先思考dp方向,然后注意废状态的处理,我由于dp数组最开始没有把状态赋为-INF,从而有些状态由一些废状态转移过来了,wa了很久。
     
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MAXN 660
    #define INF 0x3f3f3f3f
    int dp[55][MAXN];
    int tot[MAXN][MAXN];
    int stot[MAXN][MAXN];
    int tot2[MAXN][MAXN];
    int stot2[MAXN][MAXN];
    int pv[MAXN][MAXN];
    
    int main()
    {
            //freopen("input.txt","r",stdin);
            int n,m;
            scanf("%d%d",&n,&m);
            for (int i=1;i<=n;i++)
                    for (int j=i+1;j<=n;j++)
                            scanf("%d",&tot[i][j]),tot2[j][i]=tot[i][j];
            for (int i=1;i<=n;i++)
                    for (int j=i+1;j<=n;j++)
                            stot[i][j]=stot[i][j-1]+tot[i][j];
            for (int i=1;i<=n;i++)
                    for (int j=1;j<i;j++)
                            stot2[i][j]=stot2[i][j-1]+tot2[i][j];
            for (int i=0;i<MAXN;i++)
                    for (int j=0;j<MAXN;j++)
                            dp[i][j]=-INF;
            for (int i=1;i<=n;i++)
                    dp[0][i]=0;
            for (register int p=1;p<=m;p++)
            {
                    for (int i=1;i<=n;i++)
                    {
                            int v=0;
                            for (int k=i;k<n;k++)
                            {
                                    v+=stot[k][n];
                                    v-=stot2[k][k-1]-stot2[k][i-1];
                                    if (dp[p][i]<dp[p-1][k+1]+v)
                                    {
                                            dp[p][i]=dp[p-1][k+1]+v;
                                            pv[p][i]=k+1;
                                    }
                            }
                    }
            }
            //printf("%d
    ",dp[m][1]);
            int cur=1;
            for (int i=0;i<m-1;i++)
            {
                    cur=pv[m-i][cur];
                    printf("%d ",cur-1);
            }
            cur=pv[m-(m-1)][cur];
            printf("%d",cur-1);
            printf("
    ");
    }
  • 相关阅读:
    【转载】使用缓存的9个误区(上)
    .NET开发者必备的工具箱(转载)
    Java基础之反射(一)
    【干货转载】.NET中的六个重要概念:栈、堆、值类型、引用类型、装箱和拆箱
    CKEditor配置详解
    ASP.NET中IsPostBack的理解
    三层架构与设计模式思想部署企业级数据库业务系统开发
    AppDomain 详解(转)
    字符串基础总结
    访问数据库的时候报错 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4562684.html
Copyright © 2011-2022 走看看