• 21.11.12模拟 P3486 [POI2009]KON-Ticket Inspector


    看到数据,显然很可能是(n^2k)的暴力DP,题目要求查询不同的人,就是个二维前缀和的过程。加入在i站查,上次查是j站,那么就是在j+1 ~ i上站,i+1 ~ n下站的人数,二维前缀和即可

    注意,第i站是先下车再查询,

    [f[i][k]表示第i站查第k次的最大价值, \ f[i][k]=max(f[j][k-1]+val), 0 le j < i ]

    题目要求输出最小字典序,我们开个pre记录即可。记录能达到最大价值查k次的最小i,再往前找答案,这样的字典序是最小的

    const int N = 607;
    int f[N][57], pre[N][57]; 
    int a[N][N];
    int n, K, ans[N];
    
    inline int sum(int x2, int y2, int x1, int y1) {
    	return a[x2][y2] + a[x1-1][y1-1] - a[x1-1][y2] - a[x2][y1-1];
    }
    int main() {
    	freopen("ticket.in", "r", stdin);
    	freopen("ticket.out", "w", stdout);
    	read(n);
    	read(K);
    	rep(i, 1, n) {
    		rep(j, i+1, n) {
    			read(a[i][j]);
    		}
    	}
    	rep(i, 1, n) {
    		rep(j, 1, n) {
    			a[i][j] += a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];
    		}
    	}
    
    	memset(f, 0xcf, sizeof f);
    	f[0][0] = 0;
    	int mx(0),last(0);
    	rep(k, 1, K) {
    		rep(i, 1, n - 1) {
    			rep(j, 0, i - 1) {
    				int val = sum(i, n, j + 1, i + 1);
    				if(f[i][k] < f[j][k - 1] + val) {
    					f[i][k] = f[j][k - 1] + val;
    					pre[i][k] = j;
    				}
    			}
    			if(k == K && f[i][k] > mx) {
    				mx = f[i][k];
    				last= i;
    			}
    		}
    	}
    	int j(last);
    	int t(K);
    	do {
    		ans[t] = j;
    		j = pre[j][t];
    	}while(t--);
    	rep(i, 1, K) {
    		out(ans[i], ' ');
    	}
    	putchar('
    ');
    	return 0;
    }
    

    本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15547297.html

  • 相关阅读:
    NSDate 与NSString的互相转换
    NSArray 基础
    IOS 使用自定义字体
    页面跳转添加动画
    Builder 模式
    树的子结构
    Singleton 模式
    合并两个排序的链表(递归算法)
    合并两个排序的链表(非递归)
    反转链表
  • 原文地址:https://www.cnblogs.com/QQ2519/p/15547297.html
Copyright © 2020-2023  润新知