好美的题目描述~好有文采啊~我也要和星星玩...TAT
1.星海
AQ从小就希望能够摘下漫天星空中的星星,满载一船星辉,在星辉斑斓里放歌。
一天AQ 正在沉浸于自己的想象中的时候,星辉女神出现在了AQ 的面前。星辉女神给了AQ 几个闪烁光辉的盆子,
并告诉他,只要在盆子里放进清水,在这个夏夜的星海里,爱玩的星星们便会纷纷下落,进入盆子中嬉戏玩水。只要AQ及时抓住星星们,就可以天天与星星们游戏。
AQ希望有尽量多的星星与他游戏。但是星辉女神给 的盆子有一定的大小,每个星星也有一定的体积。
给出每个盆子的大小与星星的体积,请求出 最多能有多少的星星与他游戏。
基础的搜索题..想复杂了。
不过有各种技巧。
首先这道题必须迭代(二分深度或枚举深度都行)
原因在于为了加速,我们要从大到小枚举星星在哪个盆子。这样可以减少搜索枝。
经测试一个0.02的点如果从小到大枚举可以超时..差别巨大啊。
然后加几个剪枝。
1.如果这个星星的体积和上一个一样,那么有个小剪枝(详见程序)否则超3个点。
2.剩余空间已经不够了,直接return false
然后就过了..TAT..
code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<climits>
#include<algorithm>
#include<cstring>
#include<windows.h>
#define ot "%d"
#define kg " "
#define kh "\n"
#define olt "%I64d"
#define ll long long
#define max(a, b) ({int _ = (a), __ = (b); _ > __ ? _ : __;})
#define min(a, b) ({int _ = (a), __ = (b); _ < __ ? _ : __;})
#define swap(a, b) ({int _ = (a); a = (b); b = _;})
#define maxn 55
#define maxm 1025
using namespace std;
int n, m, aa[maxn], a[maxn], b[maxm], waste, limit, tot, sum[maxn];
void init()
{
freopen("star.in", "r", stdin);
freopen("star.out", "w", stdout); tot = 0;
scanf(ot, &n); for (int i = 1; i <= n; ++i) scanf(ot, &a[i]), tot += a[i];
scanf(ot, &m); for (int i = 1; i <= m; ++i) scanf(ot, &b[i]);
sort(a + 1, a + n + 1); sort(b + 1, b + m + 1); sum[0] = 0;
for (int i = 1; i <= m; ++i) sum[i] = sum[i - 1] + b[i];
}
bool dfs(int res, int k)
{
if (!res) return 1;
if (waste > limit) return 0;
for (int i = k; i <= n; ++i)
if (a[i] >= b[res])
{
a[i] -= b[res];
if (a[i] < b[1]) waste += a[i];
if (b[res] == b[res - 1]) if (dfs(res - 1, i)) return 1; else; //The 'so-called' little prune
else if (dfs(res - 1, 1)) return 1;
if (a[i] < b[1]) waste -= a[i];
a[i] += b[res];
}
return 0;
}
int main()
{
init();
int l = 0, r = m, mid;
memcpy(aa, a, sizeof a);
while (l != r)
{
mid = (l + r + 1) >> 1; waste = 0; limit = tot - sum[mid];
if (dfs(mid, 1)) l = mid; else r = mid - 1;
memcpy(a, aa, sizeof a);
}
printf(ot, l);
return 0;
}