Description
Write a program that, knowing the height of each soldier, determines the minimum number of soldiers which have to get out of line.
Input
There are some restrictions:
• 2 <= n <= 1000
• the height are floating numbers from the interval [0.5, 2.5]
Output
Sample Input
8 1.86 1.86 1.30621 2 1.4 1 1.97 2.2
Sample Output
4
题解:可以直接将这个问题轻松转化为01背包,但复杂度为V*∑n[i]比较高,所以需要优化:
解题过程:对于每个物品,有三种情况:
①:单件该物品体积已经超过背包容量,不可能装的进
②:无法将该物品全部装入背包,直接将它当做完全背包
③:可以将该物品全部装入背包,这种情况比较复杂,可以将这些物品拆成多个单件物品,但复杂度很高(V*∑n[i]),所以需要二进制优化,
假设有30个该物品,每件物品体积为10,将这30个物品拆成5个单件物品即可,它们的体积分别为10、20、40、80、150,这样对于任意的m(m<=30)
件物品都可以用这5个物品表示出来
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[100005], V;
void Alone(int use)
{
int v;
for(v=V;v>=use;v--)
dp[v] = max(dp[v], dp[v-use]+use);
}
void Every(int use)
{
int v;
for(v=use;v<=V;v++)
dp[v] = max(dp[v], dp[v-use]+use);
}
void Mulitp(int n, int use)
{
int k;
if(use>V)
return;
if(use*n>=V)
Every(use);
else
{
k = 1;
while(k<n)
{
Alone(k*use);
n -= k;
k *= 2;
}
Alone(n*use);
}
}
int main(void)
{
int i, n, s[15], val[15];
while(scanf("%d", &V)!=EOF)
{
memset(dp, 0, sizeof(dp));
scanf("%d", &n);
for(i=1;i<=n;i++)
scanf("%d%d", &s[i], &val[i]);
for(i=1;i<=n;i++)
Mulitp(s[i], val[i]);
printf("%d\n", dp[V]);
}
}