LightOJ 1235 - Coin Change (IV) (折半枚举)

题目链接:

  http://www.lightoj.com/volume_showproblem.php?problem=1235

题目描述:

  给出n个硬币,每种硬币最多使用两次,问能否组成K面值?

解题思路:

  因为K草鸡大,尽管n很小,但是2^n很大,无法用背包做到O(nK)的复杂度。如果暴力枚举复杂度立马飙升到O(2^(n+1))。···········

  所以引进一种新的算法,折半查找:把所要枚举的值,先把前部分的值所有情况枚举出来,再把后部分的值所有情况枚举出来并排序,结合二分进行查找。 这样可以把复杂度降到O(2^(n/2)*log2(n))。

  最近不做题,感觉自己萌萌哒。大家玩敲七,到我这里,我总是一脸懵逼的样子。希望一天一个dp,到老也能萌萌哒  (。?`ω´?)

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7
 8 #define maxn 20000
 9 int cnt1, cnt2, k, n, num;
10 int a1[maxn], a2[maxn], b[20];
11
12 void dfs (int sum, int x)
13 {
14     if (x == num)
15     {
16         num == n/2 ? a1[cnt1++] = sum : a2[cnt2++] = sum;
17         return ;
18     }
19     for (int i=0; i<3; i++)
20         dfs (sum+b[x]*i, x+1);
21 }
22
23 bool sreach (int x)
24 {
25     int low = 0, high = cnt2-1;
26
27     while (low <= high)
28     {
29         int mid = (low + high) / 2;
30         if (a1[x] + a2[mid] == k)
31             return true;
32         else if (a1[x] + a2[mid] > k)
33             high = mid - 1;
34         else
35             low = mid + 1;
36     }
37
38     return false;
39 }
40
41 int main ()
42 {
43     int T, l = 1;
44     scanf ("%d", &T);
45
46     while (T --)
47     {
48         scanf ("%d %d", &n, &k);
49         for (int i=0; i<n; i++)
50             scanf ("%d", &b[i]);
51
52         cnt1 = cnt2 = 0;
53         num = n / 2;
54         dfs (0, 0);
55
56         num = n;
57         dfs (0, n/2);
58         sort (a2, a2 + cnt2);
59
60         int i;
61         for (i=0; i<cnt1; i++)
62         {
63             if (sreach (i))
64                 break;
65         }
66         if (i == cnt1) printf("Case %d: No\n", l++);
67         else printf ("Case %d: Yes\n", l++);
68     }
69     return 0;
70 }
时间: 2024-10-23 04:43:24

LightOJ 1235 - Coin Change (IV) (折半枚举)的相关文章

lightoj 1235 Coin Change (IV)(折半枚举)

话说这是俺们学校暑假集训完的一道题,刚看到以为是到水题,后来发现者复杂度也太大了,受不了了,比赛完也没搞出来,然后欣爷说这是折半枚举.然后就摸摸的学了一下,又把这道题写了一下, 所谓折半枚举就是先算出来一半,再算一半,然后用二分查找看看能不能搞到这一发状态,可以的话就是可以了, 题意:给你两个数n,k,下面再给你n个数,表示你现在有的硬币的面值,每种硬币面值的有两个,看是否可以支付k 题解思路:首先以为只有三种状态,直接dfs就好了,后来发现复杂度太大了,然后死了撸就是上面的,详细情残考代码 源

Lightoj 1235 - Coin Change (IV) 【二分】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1235 题意: 有N个硬币(N<=18).问是否能在每一个硬币使用不超过两次的情况下支付正好K的面额. 思路 : dfs构造出用这些硬币用前一半能支付的全部费用和后一半能支付的全部费用. 之后排序,枚举前一半的每一个面值在第二个里面二分寻找就可以.(或者用set保存). 代码:(set) #include <stdio.h> #include <ctime>

1235 - Coin Change (IV)

   PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 32 MB Given n coins, values of them are A1, A2 ... An respectively, you have to find whether you can pay K using the coins. You can use any coin at most two times. Input Input st

Lightoj 1231 - Coin Change (I) (裸裸的多重背包)

题目链接: Lightoj  1231 - Coin Change (I) 题目描述: 就是有n种硬币,每种硬币有两个属性(价值,数目).问用给定的硬币组成K面值,有多少种方案? 解题思路: 赤果果的多重背包,简单搞一下就好了.席八!烦烦烦.今天绝对是出门刷提前没看黄历,刚开始套了一个多重背包板子,蓝而跑出来的答案并不对,改来改去就错在细节的地方. 1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4

LightOj 1076 - Get the Containers (折半枚举 绝世好题)

题目链接: http://www.lightoj.com/volume_showproblem.php?problem=1076 题目描述: 给出n个数,要求分成m段,问这m段中最大的总和,最小是多少? 解题思路: 二分每一段的长度,然后判定枚举长度是否合法. 刚看到这个题目就想到了dp,但是dp的复杂度还是很高的,然后就一直放着,放着....学了折半枚举,拿起来一看,哇塞,简直惊喜啊! 1 #include<cstdio> 2 #include<cstring> 3 #inclu

LightOJ 1231 Coin Change (I) (背包计数模板题)

1231 - Coin Change (I) PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 32 MB In a strange shop there are n types of coins of valueA1, A2 ... An.C1, C2,... Cn denote the number of coins of valueA1, A2... An respectively. You have

LightOJ 1231 - Coin Change (I) 【DP】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1231 题意:多重部分和的解法有几种. 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #include <string> #include <functional&

LightOJ 1232 - Coin Change (II) 【完全背包】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1232 题意:每个物品价值为val[i] (>=1),每个物品有k种,组成价值为k的方案数.完全背包. 解法:完全背包计数. 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #i

hdu 2069 Coin Change 背包。本来打算用母函数再写一遍的,发现代码极其相似,就没写

Coin Change Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 14982    Accepted Submission(s): 5070 Problem Description Suppose there are 5 types of coins: 50-cent, 25-cent, 10-cent, 5-cent, and