zoukankan      html  css  js  c++  java
  • 西电oj 1036 dp(01背包)

    西电oj 1036    dp(01背包)

    1036: 分配宝藏

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 40  解决: 11
    [提交][状态][讨论版]

    题目描述

    两个寻宝者找到一个宝藏,里面包含着n件物品,每件物品的价值是w[i]。suma代表寻宝者A所获物品的总价值,sumb代表寻宝者B所获物品的总价值,请问怎么分配,能使得|suma - sumb|(即suma与sumb之差的绝对值)最小。

    输入

    有多组输入数据,第一行为一个数字T,代表有T组输入数据 (0<T<=50)。
    接下来为T组数据,每组数据分为两行:
    第一行有一个整数n, 表示物品个数,其中0<n<=200.
    第二行有n个整数,第i个正数w[i]代表第i件物品的价值,其中0<w[i]<=200.
    注意:所有数据均为正整数。

    输出

    一共T行。
    对于每组数据,输出一个整数,表示|suma-sumb|。

    样例输入

    2
    2
    2 3
    4
    1 2 3 4

    样例输出

    1
    0

    思路:这题就是01背包的变种,一开始傻逼的去二进制枚举,直接TLErush。。。
    dp(i,j)表示第i次取了重量j到A中A-B的差值,状态转移方程abs(dp(i,j))=min(abs(dp(i-1,j-w[i])+2*w[i]),abs(dp(i-1,j));
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<math.h>
    
    using namespace std;
    
    const int maxn=31000;
    const int INF=(1<<29);
    
    int T;
    int n,w[maxn];
    int dp[310][maxn];
    int sum;
    
    int main()
    {
        cin>>T;
        while(T--){
            cin>>n;
            sum=0;
            for(int i=1;i<=n;i++){
                scanf("%d",&w[i]);
                sum+=w[i];
            }
            memset(dp,0,sizeof(dp));
            for(int i=0;i<=sum;i++) dp[0][i]=-sum;
            for(int i=1;i<=n;i++){
                for(int j=0;j<=sum;j++){
                    if(j-w[i]>=0){
                        int a=dp[i-1][j-w[i]]+2*w[i];
                        int b=dp[i-1][j];
                        if(abs(a)<abs(b)) dp[i][j]=a;
                        else dp[i][j]=b;
                    }
                    else dp[i][j]=dp[i-1][j];
                }
            }
            int ans=INF;
            for(int i=0;i<=sum;i++){
                if(abs(dp[n][i])<ans) ans=abs(dp[n][i]);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    剑指offer--26.顺时针打印矩阵
    剑指offer--25.二叉树的镜像
    剑指offer--24.树的子结构
    剑指offer--23.合并两个排序的链表
    剑指offer--22.反转链表
    剑指offer--21.链表中倒数第k个结点
    剑指offer--20.矩形覆盖
    剑指offer--19.重建二叉树
    剑指offer--18.从尾到头打印链表
    剑指offer--17.第一个只出现一次的字符
  • 原文地址:https://www.cnblogs.com/--560/p/4500018.html
Copyright © 2011-2022 走看看