P1510 精卫填海
最初思路
状态方程F[i]
,i
是体积,F[i]
指能填平该体积的最小体力。
推出转移方程F[i] = min(F[i], F[i-v[i]] + m[i])
但是代码实现只有10pts
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int v, n, c;
int k[10010], m[10010];
int F[100100];
int main() {
cin >> v >> n >> c;
for (int i = 1; i <= n; i++) {
cin >> k[i] >> m[i];
}
for (int i = 1; i <= v + 5000; i++) {
F[i] = 0x3f3f3f;
}
for (int i = 1; i <= n; i++) {
for (int j = v; j >= k[i]; j--) {
F[j] = min(F[j], F[j - k[i]] + m[i]);
}
}
if (c - F[v] >= 0)
cout << c - F[v];
else
cout << "Impossible";
return 0;
}
思路改进
如果是按照\(01\)背包,这层for循环枚举到k[i]
是没问题的
for (int j = v; j >= k[i]; j--)
{
F[j] = min(F[j], F[j - k[i]] + m[i]);
}
但是这是一个求最小值的问题,01背包不需要枚举\(j\)从零到\(k[i]\)的值是因为这些值本该为0,已经被提前初始化好了。
而求最小值的话,\(j\)从零到\(k[i]\)时要等于说要装填一个小于当前物品体积的东西,那只能取当前物品的体力值,毕竟没有比当前物品体积小的东西了,所以应加上\(j\)从零到\(k[i]\)的处理
for (int i = 1; i <= n; i++)
{
for (int j = v; j >= 0; j--)
{
if (j >= k[i])
F[j] = min(F[j], F[j - k[i]] + m[i]);
else
F[j] = min(F[j], m[i]);
}
}
标签:精卫填海,min,int,P1510,零到,include
From: https://www.cnblogs.com/kdlyh/p/17807142.html