zoukankan      html  css  js  c++  java
  • poj1015 Jury Compromise

    dp

    本题为special judge,不需要考虑多解情况。

    f[i][j]表示在选m个人中的选i个人的时候使所有已选中的人的p,d差为j时,所能获得的p,d最大和。

    f[i + 1][j + p[k] - d[k]] = f[i][j] + p[k] + d[k];(要求k之前没有选过,要查看f[i][j]的完整路径,确保无k)

    填写完成后,观察f[m]找到最小差值,最大和。知道和差自然可以求出总的p,d。

    也可以用另一种方法:

    三维f[i,j,k]表示前i取j差值为k的最大和

    f[i,j,k]=max{f[i-1,j,k],f[i-1,j-1,k-s1[i]]+s2[i]}

    我用的第一个:

    /**
     * Problem:POJ1015
     * Author:Shun Yao
     * Time:2013.6.2
     * Result:Accepted
     * Memo:DP
     */
    
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    
    long n, m, f[25][805], path[25][805], p[205], d[205], ans[205];
    char vis[205];
    
    int main() {
    	long i, j, k, t1, t2, tcase, w;
    	freopen("poj1015.in", "r", stdin);
    	freopen("poj1015.out", "w", stdout);
    	tcase = 0;
    	while (scanf("%ld%ld", &n, &m), n) {
    		w = m * 20;
    		for (i = 1; i <= n; ++i)
    			scanf("%ld%ld", p + i, d + i);
    		for (j = 0; j <= m; ++j) {
    			memset(f[j], 0xff, sizeof f[j]);
    			memset(path[j], 0, sizeof path[j]);
    		}
    		f[0][w] = 0;
    		for (j = 0; j < m; ++j)
    			for (k = 0; k <= (w << 1); ++k)
    				if (f[j][k] >= 0) {
    					memset(vis, 0, sizeof vis);
    					t1 = j;
    					t2 = k;
    					while (t1) {
    						vis[path[t1][t2]] = 1;
    						t2 -= p[path[t1][t2]] - d[path[t1][t2]];
    						--t1;
    					}
    					for (i = 1; i <= n; ++i)
    						if (!vis[i] && f[j + 1][k + p[i] - d[i]] < f[j][k] + p[i] + d[i]) {
    							f[j + 1][k + p[i] - d[i]] = f[j][k] + p[i] + d[i];
    							path[j + 1][k + p[i] - d[i]] = i;
    						}
    				}
    		i = w;
    		j = 0;
    		while (f[m][i - j] < 0 && f[m][i + j] < 0)
    			++j;
    		if (f[m][i - j] > f[m][i + j])
    			k = i - j;
    		else
    			k = i + j;
    		printf("Jury #%ld\n", ++tcase);
    		printf("Best jury has value %ld for prosecution and value %ld for defence:\n", (f[m][k] + k - w) >> 1, (f[m][k] - k + w) >> 1);
    		for (i = m; i >= 1; --i) {
    			ans[i] = path[i][k];
    			k -= p[ans[i]] - d[ans[i]];
    		}
    		std::sort(ans + 1, ans + m + 1);
    		for (i = 1; i <= m; ++i)
    			printf(" %ld", ans[i]);
    		puts("\n");
    	}
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    java 整合redis缓存 SSM 后台框架 rest接口 shiro druid maven bootstrap html5
    《将博客搬至CSDN》
    前后端分离-定义响应格式化数据
    微服务-Springboot+Redis缓存管理接口代码实现
    java语法
    java后台树形结构展示---懒加载
    后端处理前端传过来的日期的两种方式
    汉字转拼音工具类
    Mybatis的小技巧
    调用高德API,通过输入的地址,如省份、市、区获取经纬度 ,通过输入的经纬度,获取区域详情
  • 原文地址:https://www.cnblogs.com/hsuppr/p/3114380.html
Copyright © 2011-2022 走看看