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 }
  • 相关阅读:
    在ASP.NET AJAX中防止用户多次提交页面
    谈谈对C#委托的理解,附代码实例
    如何用VS2005制作Web安装程序 (转)
    VS2005下BoundField的DataFormatString不起作用了?
    使用XMLHttp在页面间传送参数
    远程连接sql server 2000服务器的解决方案
    JavaScript获取元素在浏览器画布中的绝对位置
    旧神谱
    [转帖]IE经典故障写真
    希腊神话
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/5405870.html
Copyright © 2011-2022 走看看