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;
    }
    
  • 相关阅读:
    网络编程_UDP协议_发送端与接收端
    网络编程_IP对象_InetAddress
    Java对XML文件解析方式之一_SAX
    GUI练习3
    GUI_菜单练习
    GUI_文件管理器(练习)
    HTTP数据组织方式
    web前端面试题
    19-字符串匹配(kmp || substr,find)
    17-逆序数(树状数组+离散)
  • 原文地址:https://www.cnblogs.com/hsuppr/p/3114380.html
Copyright © 2011-2022 走看看