lightoj 1127 Funny Knapsack | 二分+折半枚举

2024-06-12 11:48

本文主要是介绍lightoj 1127 Funny Knapsack | 二分+折半枚举,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

折半枚举这个概念在watashi所翻译的书上有介绍过。

所谓的折半枚举:把所要枚举的值,先把前部分的值所有情况枚举出来,再把后部分的值所有情况枚举出来并排序,结合二分搜索进行查找的想法。(主要是应对直接暴力枚举会超时的情况)。看完这题估计就懂了。

题意:

给你n个数,每个数都有可以取或者不取,使它们的和<=W。让你求出总的方法数。

思路:

n最大为30,如果直接枚举,时间复杂度为2^30,相当于10^9,一定会TLE。

假设n=30。先把前面15个数枚举一遍并保存,O(2^15)复杂度可以接受。然后把后15个数也枚举一遍,并从小到大排序。把前15个枚举得到的结果逐个对后部分枚举的结果进行二分搜索。找出符合条件的个数即可。复杂度瞬间降低许多。

*注意long long

AC代码:

#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <iomanip>
typedef long long ll;
using namespace std;
const double PI = acos(-1.0);
const int MAXN = 1e5+5;
ll a[MAXN], sum1[35005], sum2[35005];
int stopf, n;
ll w;
int cot1, cot2;
void dfs(int index, ll sum)
{if(index == stopf){stopf == n/2 ? sum1[cot1++] = sum : sum2[cot2++] = sum;return ;}for(int i = 0;i <= 1; i++)dfs(index+1, sum+a[index]*i);
}int main()
{ios::sync_with_stdio(false);int t, cas = 0;cin>>t;while(t--){cot1 = cot2 = 0;cin>>n>>w;for(int i = 0;i < n; i++)cin>>a[i];//stopf = n/2;dfs(0, 0);stopf = n;dfs(n/2, 0);sort(sum2, sum2+cot2);//int cot = 0;for(int i = 0;i < cot1; i++){int l = 0, r = cot2-1;int ans = -1;while(l <= r){int mid = (l+r)/2;if((ll)sum1[i] + sum2[mid] <= w){ans = mid;l = mid+1;}else    r = mid-1;}cot += ans+1;}cout<<"Case "<<++cas<<": "<<cot<<endl;}return 0;
}


这篇关于lightoj 1127 Funny Knapsack | 二分+折半枚举的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1054130

相关文章

C#实现获得某个枚举的所有名称

《C#实现获得某个枚举的所有名称》这篇文章主要为大家详细介绍了C#如何实现获得某个枚举的所有名称,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... C#中获得某个枚举的所有名称using System;using System.Collections.Generic;usi

Java 枚举的常用技巧汇总

《Java枚举的常用技巧汇总》在Java中,枚举类型是一种特殊的数据类型,允许定义一组固定的常量,默认情况下,toString方法返回枚举常量的名称,本文提供了一个完整的代码示例,展示了如何在Jav... 目录一、枚举的基本概念1. 什么是枚举?2. 基本枚举示例3. 枚举的优势二、枚举的高级用法1. 枚举

Rust中的Option枚举快速入门教程

《Rust中的Option枚举快速入门教程》Rust中的Option枚举用于表示可能不存在的值,提供了多种方法来处理这些值,避免了空指针异常,文章介绍了Option的定义、常见方法、使用场景以及注意事... 目录引言Option介绍Option的常见方法Option使用场景场景一:函数返回可能不存在的值场景

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu2289(简单二分)

虽说是简单二分,但是我还是wa死了  题意:已知圆台的体积,求高度 首先要知道圆台体积怎么求:设上下底的半径分别为r1,r2,高为h,V = PI*(r1*r1+r1*r2+r2*r2)*h/3 然后以h进行二分 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#includ

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

poj 3104 二分答案

题意: n件湿度为num的衣服,每秒钟自己可以蒸发掉1个湿度。 然而如果使用了暖炉,每秒可以烧掉k个湿度,但不计算蒸发了。 现在问这么多的衣服,怎么烧事件最短。 解析: 二分答案咯。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <c

poj 3258 二分最小值最大

题意: 有一些石头排成一条线,第一个和最后一个不能去掉。 其余的共可以去掉m块,要使去掉后石头间距的最小值最大。 解析: 二分石头,最小值最大。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <c

poj 1127 线段相交的判定

题意: 有n根木棍,每根的端点坐标分别是 px, py, qx, qy。 判断每对木棍是否相连,当他们之间有公共点时,就认为他们相连。 并且通过相连的木棍相连的木棍也是相连的。 解析: 线段相交的判定。 首先,模板中的线段相交是不判端点的,所以要加一个端点在直线上的判定; 然后,端点在直线上的判定这个函数是不判定两个端点是同一个端点的情况的,所以要加是否端点相等的判断。 最后