zoukankan      html  css  js  c++  java
  • [第四场T3]Kas

    题目描述

    Kile和Pogi在街上捡到了N张钞票。在确定无法找到失主之后,两人决定将钞票平分。他们想要得到相同数量的钱,所以他们将这些钞票尽可能分成价值相等的两份。但是当钞票无法平分的时候会剩下一些。

    由于他们不能将剩余的钞票留在街上,他们决定去附近的赌场并将所有剩下的钞票都押上,希望最终得到两倍的赌注。幸运的是他们真的让赌注翻倍了,于是Kile和Pogi平分了赢的钱。

    由于极度兴奋,他们失去了计算能力,请你帮助他们计算出每人带回家了多少钱。

    输入

    第一行输入包含一个整数N(1≤N≤500)。表示钞票的张数。

    接下来N行每行包含一个整数Ci。第i+1行的整数Ci表示第i张钞票的面额。保证N张钞票的总值不超过1e5。

    输出

    输出一个整数。表示两人分别带回家的钱。

    前方高能

    解题思路

    很明显嘛,DP,然而并不会打。考场搞半天,弄出来一个玄学的,本来暴力可以50,结果又因为绑点,玄学操作搞得1分都没有...

    首先考虑三维

    dp[i][j][k]表示用前i张钱可不可以令第一个人取j元,第二个人取k元。显然这样弄70分就有了。

    显然空间时间要爆炸。

    我们再考虑一下。

    dp[i][j]表示用前i张钱令两人取的钱的差值为j的取的钱的总和最大值。

    有些东西还是自己想会好做一下,

    相信dp定义一出来还是很容易推的。

    70分:

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    int n,c[100005],sum;
    bool dp[505][1005][1005];
    int main(){
    	//freopen("kas.in","r",stdin);
    //	freopen("kas.out","w",stdout);
    	scanf("%d",&n);
    	for (int i = 1;i <= n;i ++){
    		scanf ("%d",&c[i]);
    		sum += c[i];
    	}
    	dp[0][0][0] = 1;
    	for (int i = 1;i <= n;i ++){
    		for (int j = 0;j <= sum;j ++){
    			for (int k = 0;k <= sum;k ++){
    				if (j >= c[i])
    					dp[i][j][k] = max(dp[i][j][k],dp[i - 1][j - c[i]][k]);
    				if (k >= c[i])
    					dp[i][j][k] = max(dp[i][j][k],dp[i - 1][j][k - c[i]]);
    				dp[i][j][k] = max(dp[i][j][k],dp[i - 1][j][k]);
    			}
    		}
    	}
    	for (int i = sum;i >= 0;i --){
    		if (dp[n][i][i]){
    			printf("%d
    ",sum - i);
    			return 0;
    		}
    	}
    }

    100分:

    这里有一个清空问题,本人是这样理解的。

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    int n,c[100005],sum;
    int dp[505][100005];
    int main(){
    	//freopen("kas.in","r",stdin);
    	//	freopen("kas.out","w",stdout);
    	scanf("%d",&n);
    	for (int i = 1;i <= n;i ++){
    		scanf ("%d",&c[i]);
    		sum += c[i];
    	}
    	memset(dp,-0x3f,sizeof(dp));//这里为何要清负数?因为可能你在转移的时候,有一些DP的值根本没有更新。
    	//然而你如果仅仅是0,加上c[i]就有可能大于当前DP,因而做出了一个错误的转移
    	dp[0][0]=0;
    	for (int i = 1;i <= n;i ++){
    		for(int j = 0;j <= sum;j ++){
    			dp[i][j] = dp[i - 1][j];
    			dp[i][j] = max(dp[i - 1][j + c[i]] + c[i],dp[i][j]);
    			dp[i][j] = max(dp[i - 1][abs(j - c[i])] + c[i],dp[i][j]);
    		}
    	}
    	printf("%d",sum - dp[n][0] / 2);
    }
  • 相关阅读:
    inux按照CPU、内存、磁盘IO、网络性能监测
    监控数据库
    NMON监控工具
    AJAX
    性能经验之谈【转】
    内存/硬盘/io关系
    testng中添加案例失败重试次数
    如何使用beanshell写入数据到文件(txt、csv)
    Docker 容器中配置nginx后报403 Forbidden 解决办法
    Centos7创建支持ssh服务器的docker容器
  • 原文地址:https://www.cnblogs.com/lover-fucker/p/13566670.html
Copyright © 2011-2022 走看看