zoukankan      html  css  js  c++  java
  • LightOJ 1235

    题目链接:

      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
    ", l++);
    67         else printf ("Case %d: Yes
    ", l++);
    68     }
    69     return 0;
    70 }
  • 相关阅读:
    Java uuid生成随机32位
    Java 、C# Excel模板,数据一对多,主从表关系,导入到数据库
    ROS 八叉树地图构建
    操作系统基础信息搜集
    菜鸟的信息安全学习之路
    提权初探
    Windos/Linux 反弹 shell
    初读鸟哥的linux私房菜的收获
    linux中find命令的摘要
    分享一个Flink checkpoint失败的问题和解决办法
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/5405870.html
Copyright © 2011-2022 走看看