状压dp-基础题目2([USACO12MAR] Cows in a Skyscraper G)

题目链接

做题反思

这题我一开始没过Subtask #1,当时想的是dp数组存储电梯承载奶牛集合s(二进制转整数)需要的最少趟数,再开一个数组z,存储奶牛集合s的重量,如果zs>w,则让zs%w。这是不对的,比如Subtask #1的数据最大载重w为10,4头奶牛的重量为9,9,9,2,用这个思路,答案是3。问题就在于这种做法会把奶牛"分身"乘坐电梯,比如前两头奶牛,有一头奶牛会有1重量在1趟电梯,另外8重量在另一趟电梯,这就有问题了。

题目正解
  • 数组定义
    我们定义一个数组dp,dpij表示第i趟运送奶牛集合j的重量。初始化dp数组为0x3f3f3f3f,dp00=0,dp11\<\<(i-1)=ci
  • 状态转移
    外层遍历趟数,循环遍历为i,范围是1至n。内层循环遍历集合j,范围0至(1<<n),我们看一下用i趟运送奶牛集合j是否能实现,如果可以,则再遍历新加入奶牛,循环变量k,范围是1至n。通过移位运算和与运算判断集合j时候有奶牛k,如果没有就看一下当前dpij+ck是否大于w,如果是,要新开一趟,dpi+1j\|(1\<\<(k-1))=min(dpi + 1j \| (1 \<\< k - 1),ck);否则, dpij \| (1 \<\< k - 1) = min(dpij \| (1 \<\< k - 1), dpij + ck)。
  • 输出答案
    循环变量i遍历1至n,输出第一个dpi(1\<\<0x3f3f3f3f的值,结束。
AC代码
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int w, c[20], dp[20][1 << 20], n;

int main() {
	cin >> n >> w;
	memset(dp, 0x3f, sizeof(dp));
	dp[0][0] = 0;
	for (int i = 1; i <= n; i++) {
		cin >> c[i];
		dp[1][1 << (i - 1)] = c[i];
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < (1 << n); j++) {
			if (dp[i][j] < 0x3f3f3f3f) {
				for (int k = 1; k <= n; k++) {
					if (!((1 << k - 1)&j)) {
						if (dp[i][j] + c[k] > w)
							dp[i + 1][j | (1 << k - 1)] = min(dp[i + 1][j | (1 << k - 1)], c[k]);
						else
							dp[i][j | (1 << k - 1)] = min(dp[i][j | (1 << k - 1)], dp[i][j] + c[k]);
					}
				}
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		if (dp[i][(1 << n) - 1] < 0x3f3f3f3f) {
			cout << i;
			break;
		}
	}
	return 0;
}
相关推荐
吃好睡好便好1 小时前
查找函数的使用
学习·算法·matlab·生活·查找函数
学习星球1 小时前
单调栈——从“找下一个更大的“到柱状图中的最大矩形
数据库·c++·算法·leetcode·xcode
小灰灰搞电子2 小时前
C++ 引用折叠详解
c++
靠沿2 小时前
贪心算法专题(二)
算法·贪心算法
布莱克6052 小时前
数组详解:定义、作用、应用场景及与链表的区别(C/C++ 代码讲解)
c语言·开发语言·c++·数组
猎头南楼3 小时前
具身智能模型部署方向的能力要求与技术栈梳理
人工智能·深度学习·算法
牛油果子哥q3 小时前
C++内存池与对象池精讲:内存碎片、自定义分配器、对象池实现、STL allocator原理、工程落地与性能对比
java·开发语言·c++
万法若空4 小时前
C/C++ 类型别名定义方式对比
java·c语言·c++
啥都想学点的研究生4 小时前
一篇文章讲清楚:线性回归问题的求解——正规方程法
算法·机器学习·线性回归
青少儿编程课堂4 小时前
树状数组精讲:逆序对计数与离散化(附双语言解法)
算法·树状数组·离散化·信息学奥赛·逆序对