【二分\搜索\剪枝】软件下载

来源:互联网 发布:淘宝好做还是微店好做 编辑:程序博客网 时间:2024/06/03 16:50

3、软件下载

ICG大赛马上就要举行了,作为大赛的组委会兼参赛选手,信息组的成员们当然要做准备了,而其中十分重要的一项准备工作就是下载很多举办大赛必不可少的软件,已知现在机房有N台电脑,组委会列出了M个需要下载的软件及其大小Ai(即需要下载的时间),每个电脑同一时间只能下载一个软件,一个软件也只能由一个电脑下载,每个电脑下载速度相同且互不影响.因为有神器Cena的存在,每个软件只需由某一台电脑下载一次就能使整个机房的电脑普及该软件。现在ICG组委会想知道最快能在多长时间内下载完成。

输入格式

第1行:两个整数N、M,分别代表机房的电脑数及需要下载的软件数量。

第2行:M个整数,第i个整数表示Ai的值。

输出格式

一行一个整数,表示能下载完所有软件的最短时间。

输入样例:

2 3

1 2 3

输出样例

3

 

数据范围:

1<=n<=10

1<=m<=50



这道题比较好。因为考察了剪枝的技巧。


讨论二分的检验:

我一开始想的方法是N^M的方法,但是错误算成了M!/N!,所以导致我用了低效的方法。

正确的方法应该是M!的搜索,即先从大到小排序,依次把每一个软件分配给计算机。如果说分配不了了,那么,就分配到下一个计算机。否则可以选择分配给当前计算机,或者暂时不,转而判断下一个软件。

这样做仍然过不了。但是考虑而我们事先排了序,越到后面越小,假设我们以最优情况考虑,让每台电脑都以刚好以二分出的最短时间下载完,如果说这样都还不能下载完剩余的软件,则剪枝。这样就能秒过了。


关键是在于“越到后面时间长短越小”。。


#include <cstdio>#include <string>#include <cstring>#include <algorithm>#include <functional>using std::sort;#define min(a,b) ((a)<(b)?(a):(b))#define max(a,b) ((a)>(b)?(a):(b))long m,n;long mid;long a[60];long cnt[20];bool used[60];bool can(long u,long v,long left){if ((n-u+1)*mid-cnt[u] < left)return false;if (v == m)return true;for (long i=1;i<m+1;i++){if (!used[i]){if (cnt[u] + a[i] <= mid){used[i] = true;cnt[u] += a[i];if (can(u,v+1,left-a[i])) return true;cnt[u] -= a[i];used[i] = false;}else if (u < n){used[i] = true;cnt[u+1] += a[i];if (can(u+1,v+1,left-a[i])) return true;cnt[u+1] -= a[i];used[i] = false;}else return false;}}return false;}long getint(){long rs=0;bool sgn=1;char tmp;do tmp = getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp == '-'){tmp=getchar();sgn=0;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;}int main(){freopen("soft.in","r",stdin);freopen("soft.out","w",stdout);n = getint();m = getint();long l = -0x3f3f3f3f;long r = 0;long sum = 0;for (long i=1;i<m+1;i++){a[i] = getint();r += a[i];l = max(l,a[i]);}sum = r;sort(a+1,a+1+m,std::greater<long>() );long ans = 0x3f3f3f3f;while (l <= r){mid = (l+r) >> 1;memset(used,0,sizeof used);memset(cnt,0,sizeof cnt);used[1] = true;cnt[1] = a[1];if (can(1,1,sum-a[1])){if (ans > mid)ans = mid;r = mid-1;}elsel = mid+1;}printf("%ld",ans);return 0;}


原创粉丝点击