zoukankan      html  css  js  c++  java
  • 【u220】生日礼物

    Time Limit: 1 second
    Memory Limit: 128 MB

    【问题描述】

    一对双胞胎兄妹同一天过生日,这一天,他们的朋友给他俩送来了礼物,每个人送的礼物都是2本书,一本给哥哥,一本给妹妹,但没有说
    明哪本是给妹妹的,哪本是给哥哥的,每本书都有自己的价值,为了避免冲突,让你来分配,要求使得两人所获得书本的价值和之间的
    差距尽可能的小。
    例如,有4个礼物:(3,5),(7,11),(8,8),(2,9),可以把3,7,8,2分配给妹妹,其余的给哥哥,价值差为:5+11+8+9-3-7-8-2=13;如果把3,7
    ,8,9给妹妹,其余的给哥哥,价值差为:3+7+8+9-5-11-8-2=1,这是最好的方案。


    【输入格式】

    输入文件gift.in的第一行包含一个正整数N,表示礼物的数量,接下来N行,每行两个整数,表示每份礼物两本书的价值(价值范围在1到300之间)。

    【输出格式】

    输出文件gift.out包含一个非负整数,表示最小的价值差。

    【数据规模】

    对于20%的数据,有N≤20; 对于40%的数据,有N≤50; 对于100%的数据,有N≤150。

    Sample Input1

    4
    3 5
    7 11
    8 8
    2 9
    
    
    

    Sample Output1

    1

    【题解】

    这题是把背包用作一个工具。来判断出2*n个数字按照规则不同的组合会产生的最后总价值可能是什么。

    动态转移方程这样写

    for (int i = 1; i<= n;i++)
    for (int j = 300*150+10;j>=0;j--)

    if (f[j])

    {

    f[j] = false;

    f[j+a[i][0]] = true,f[j+a[i][1] = true;

    }

    其中f[]一个bool型的一维数组。

    然后我们之所以遇到一个f[j]就把f[j]置为false,是因为。要保证每一个礼物都被用到。

    比如f[4]是前两个礼物可能达到的值,我们在更新第四个礼物的时候会遇到f[4]为true,但是我们不能用他来更新f[4+a[i][0]]或f[4+a[i][1]],因为这样我们会有第三个礼物没有用。直接跳到了第4个礼物。这样会导致最后有一些数字是在没有用满n个数字的情况下累加得到的。最后得到2*n个数字不同组合可能达到的累加和之后。我们累加所有的数字之和为dd,然后从dd/2开始枚举一直递增。直到f[i]为真。然后用k记录这个i。则dd-k就是另外一个数字。因为我们是从dd/2开始枚举的,可以肯定,这两个数字一定是最接近的。

    最后输出两个数字之差就可以了。

    【代码】

    #include <cstdio>
    #include <cmath>
    
    int n,a[151][2],dd = 0;
    bool f[300*150 + 10] = {0};
    
    int main()
    {
    	//freopen("F:\rush.txt","r",stdin);
    	scanf("%d",&n);
    	for (int i = 1;i <= n;i++)
    		scanf("%d%d",&a[i][0],&a[i][1]),dd+= (a[i][0] + a[i][1]);//dd一边累加所有的数字之和 
    	f[0] = true;
    	for (int i = 1;i <= n;i++)
    		for (int j = 300*150 +2;j >=0;j--)
    			if (f[j])
    				{
    					f[j] = false;
    					f[j+a[i][0]] = true;
    					f[j+a[i][1]] = true;	
    				} //将背包当做工具,获取最后能累加到哪些数字 
    	int k;
    	for (int i = (dd / 2);i <=dd;i++) //从dd/2开始枚举,直到找到一个数字 他可以由n个数字累加得到 
    		if (f[i])
    			{
    				k = i;
    				break;
    			}
    	int temp = dd-k; //这是另外一个数字 
    	if (temp > k) //根据大小关系输出他们的差就好了。 
    		printf("%d",temp-k);
    			else
    				printf("%d",k-temp);
    	return 0;	
    }


  • 相关阅读:
    WPF TreeView IsExpanded 绑定不上的问题
    WPF TreeView BringIntoViewBehavior
    WPF ListBox的进阶使用(二)
    WPF ListBox的进阶使用(一)
    双缓冲队列解决WPF界面卡死
    C# 对接Https接口
    软件架构的六大设计原则
    FeignClient接口封装
    CentOS修改root密码
    并发编程的挑战(Java并发编程的艺术)
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632367.html
Copyright © 2011-2022 走看看