状压dp最小分组

本文介绍了一个关于奶牛下楼的趣味问题,奶牛们在攀登完摩天大楼后不愿走楼梯下楼,于是必须使用电梯。问题转化为如何在不超过电梯最大载重的情况下,用最少的电梯次数将所有奶牛送回地面。文章通过动态规划算法解决这个问题,给出了输入格式、输出格式,并展示了一个C++实现的解决方案。

题目描述

A little known fact about Bessie and friends is that they love stair climbing races. A better known fact is that cows really don't like going down stairs. So after the cows finish racing to the top of their favorite skyscraper, they had a problem. Refusing to climb back down using the stairs, the cows are forced to use the elevator in order to get back to the ground floor.

The elevator has a maximum weight capacity of W (1 <= W <= 100,000,000) pounds and cow i weighs C_i (1 <= C_i <= W) pounds. Please help Bessie figure out how to get all the N (1 <= N <= 18) of the cows to the ground floor using the least number of elevator rides. The sum of the weights of the cows on each elevator ride must be no larger than W.

给出n个物品,体积为w[i],现把其分成若干组,要求每组总体积<=W,问最小分组。(n<=18)

输入格式

* Line 1: N and W separated by a space.

* Lines 2..1+N: Line i+1 contains the integer C_i, giving the weight of one of the cows.

输出格式

* A single integer, R, indicating the minimum number of elevator rides needed.

one of the R trips down the elevator.

#include<iostream>
#include<cstring>
using namespace std;
const int maxn=20;
int dp[1<<maxn];
int g[1<<maxn];
int val[maxn];
int main()
{
    int n,w;cin>>n>>w;
    for(int i=0;i<n;i++) cin>>val[i];
    memset(dp,0x3f,sizeof(dp));
    dp[0]=1;
    g[0]=w;
    for(int i=0;i<(1<<n);i++)
    {
        for(int j=0;j<n;j++)
        {
            if((i>>j)&1) continue;
            if(g[i]>=val[j]&&dp[i|(1<<j)]>=dp[i])
            {
                dp[i|(1<<j)]=dp[i];
                g[i|(1<<j)]=max(g[i|(1<<j)],g[i]-val[j]);
            }
            else if(g[i]<val[j]&&dp[i|(1<<j)]>=dp[i]+1)
            {
                dp[i|(1<<j)]=dp[i]+1;
                g[i|(1<<j)]=max(g[i|(1<<j)],w-val[j]);
            }
        }
    }
    cout<<dp[(1<<n)-1]<<endl;
}
帮我从dp的角度想一下这题题目描述 一群朋友去度假,有时互相借钱。 例如,爱丽丝为比尔的午餐支付了 10 10 美元。后来克里斯给爱丽丝 5 5 美元搭出租车。我们可以假设每笔交易为一个三元组 ( X , Y , Z ) (X,Y,Z),这意味着第 X X 个人借给第 Y Y 个人 Z Z 美元。假设 Alice,Bill 和 Chris 是第 0 , 1 , 2 0,1,2 个人( 0 , 1 , 2 0,1,2是他们的ID),他们之间的交易可以表示为 [ [ 0 , 1 , 10 ] , [ 2 , 0 , 5 ] ] [[0,1,10],[2,0,5]]。 给定一组人之间的交易清单,返回结算(也就是所有人都还清或收回债务,具体见样例解释)所需的最低交易数量。 输入格式 第一行两个整数 n , m n,m 分别表示人数与交易次数。 接下来 m m 行每行三个整数 x i , y i , z i x i ​ ,y i ​ ,z i ​ ,表示 x i x i ​ 借给 y i y i ​ 的金额是 z i z i ​ 。 输出格式 一个整数表示最少交易次数 样例数据 ####input1 3 2 0 1 10 2 0 5 ####output1 2 ####input2 3 4 0 1 10 1 0 1 1 2 5 2 0 5 ####output2 1 样例解释 样例1 第 0 个人借给第 1 个人10美元 第 2 个人借给第 0 个人 5美元 需要2笔交易,其中一种方式是第1个人还给第0个人和第2个人各5美元。 样例2 第0个人借给第1个人10美元 第1个人借给第0个人1美元 第1个人借给第2个人5美元 第2个人借给第0个人5美元 只需要1笔交易,第1个人还给第0个人4美元债务就还清了。 数据范围 对于 30 % 30% 的数据, n 3 n=3 对于 60 % 60% 的数据, n ≤ 5 n≤5 对于所有数据, n ≤ 16 , m ≤ 1000 , 0 ≤ x i , y i < n , 1 ≤ z i ≤ 1000 n≤16,m≤1000,0≤x i ​ ,y i ​ <n,1≤z i ​ ≤1000 时间限制 1s 空间限制 256MB
09-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值