在过去24小时里,一直被这题折腾着。。。

题目:
A Math game
Time Limit: 2000/1000MS (Java/Others) Memory Limit: 256000/128000KB (Java/Others)

Problem Description

Recently, Losanto find an interesting Math game. The rule is simple: Tell you a number H, and you can choose some numbers from a set {a[1],a[2],......,a[n]}.If the sum of the number you choose is H, then you win. Losanto just want to know whether he can win the game.

Input

There are several cases.
In each case, there are two numbers in the first line n (the size of the set) and H. The second line has n numbers {a[1],a[2],......,a[n]}.0<n<=40, 0<=H<10^9, 0<=a[i]<10^9,All the numbers are integers.

Output

If Losanto could win the game, output "Yes" in a line. Else output "No" in a line.

Sample Input

10 87
2 3 4 5 7 9 10 11 12 13
10 38
2 3 4 5 7 9 10 11 12 13

Sample Output

No
Yes

简述之就是子集和问题。

AC 之后,发现原来写代码的过程如此有趣。。。。

solution 1  直接DFS  运行时间  200.8s

针对数组中的每个元素,要么选中,要么不选。 结果是  Time Limit Exceeded (指超过题目要求的 1000MS)

遍历过程类似于二叉树,复杂度是指数级, 2^n

Solution 2 加点剪枝处理  运行时间 166.7 s

在sulotion 1 的基础上,做个判断,一旦累加的记过超过 H,则不进行后面的累加。

结果仍然 Time Limit Exceeded。 感觉没有根本性的变化!

(如果超过H的话,就不往下走了,相比第一个方案,效率有了一丢丢提升, 笔记本风扇依然狂转)

Solution 3 对输入进行预处理  运行时间 4.1 s

因为输入的数据是比较小的,所以进行排序的时间消耗非常小,但是效率的提升非常明显!

前两个方案,我等了很久,都没有出现结果。 但是排序之后,等几秒钟就看到结果了。哇,那个激动啊。。。

我画了个图,发现一旦数据是排序的,那么剪枝的效果将会非常明显,所以这导致了效率的大幅提升

虽然有所提升,但是提交之后,依然  Time Limit Exceeded (此后经过1个多小时的修改测试,还是超时) 深夜了,休息。。。

新的一天, 起床,继续 coding~~~

Solution 4 对遍历方向进行处理  运行时间  3.4 s

可能是思维惯性,老想着从无到有进行遍历,所以总是往不选的方向遍历,导致浪费很多无用的时间。

所有修改搜索顺序,往选中的方向进行遍历。

结果超时! 仔细思考之后,发现剪枝的效果不明显,原因在于我是按升序排序的,应该改为 降序排序

Solution 5  AC! 运行时间 0.4s

进行降序排序,明显提高剪枝效率,因为一旦数据超过H, 就没必要往下走了。因为是往累加的方向进行,会更快逼近结果。

至此,刚好过去了24小时,把这题的运行时间 从 200.8s 优化到了 0.4s .  总结之:就是DFS遍历应该以最优的方向进行遍历,同时进行剪枝处理

想想真的有些感动,原来自己可以如此专注。

编程要对自己有信心。 昨天是个美丽的早晨,早早起来后就开始做网络同步赛,结果一个早上,就因为这题,一直纠结着。昨晚洗澡的时候,心里就想,都有好几个人做出来了,我也一定能够做出来,睡觉的时候,也在想着,明早起来再试试,肯定可以搞出来。

上午搞不定,下午继续搞,下午搞不定,晚上继续搞,晚上搞不定,明天接着搞~~~   WA 不息,Coding 不止。

最后附上测试数据和源码

40 256
2 3 4 5 7 9 10 11 12 13 2 3 4 5 7 9 10 11 12 13 2 3 4 5 7 9 10 11 12 13 2 3 4 5 7 9 10 11 12 13

源码:

 // 给定一个集合,挑选一些数字,验证能否组成 H

 #include <iostream>
#include <cstdio>
#include <algorithm> using namespace std; int arr[] = {}; // 输入的数组 bool isFound = false; void func(const int n, const int H, int &sum, int step)
{
if (isFound)
{
return;
} if (n > step && step >= && sum < H)
{
// 先取当前这个数进行累加
sum += arr[step]; if (sum == H)
{
isFound = true;
return;
}
else if (sum < H)
{
func(n, H, sum, step+);
} sum -= arr[step]; // back trace // 不取当前数字
func(n, H, sum, step+);
}
else
{
// 结束一次选择
//cout<<sum<<endl;
if (sum == H)
{
isFound = true;
}
} } // 降序处理
bool cmp(const int a, const int b)
{
return a > b;
} int main(void)
{
freopen("in.txt","r", stdin); int n = ;
int H = ;
unsigned long long sum = ; while( scanf("%d %d", &n, &H) != EOF )
{
for(int i=; i<n; ++i)
{
scanf("%d", &arr[i]);
sum += arr[i];
} if (sum < H)
{
printf("No\n"); //这是绝对不可能的。
continue;
}
else if (sum == H) // 刚刚好全选
{
printf("Yes\n");
continue;
}
// else sum > H // 进行遍历 // 进行分解
int sum = ;
int step = ;
isFound = false; sort(arr, arr+n, cmp); // 降序排序 func(n, H, sum, step); if (isFound)
{
printf("Yes\n");
}
else
{
printf("No\n");
} } return ;
}

将 子集和问题 运行时间从 200.8s 优化到 0.4s的更多相关文章

  1. K - Large Division 判断a是否是b的倍数。 a (-10^200 ≤ a ≤ 10^200) and b (|b| > 0, b fits into a 32 bit signed integer). 思路:取余;

    /** 题目:K - Large Division 链接:https://vjudge.net/contest/154246#problem/K 题意:判断a是否是b的倍数. a (-10^200 ≤ ...

  2. NYOJ-20 吝啬的国度 AC 分类: NYOJ 2014-01-23 12:18 200人阅读 评论(0) 收藏

    #include<cstdio> #include<cstring> #include<vector> using namespace std; int pre[1 ...

  3. APP被苹果APPStore拒绝的各种原因 分类: ios相关 app相关 2015-06-25 17:27 200人阅读 评论(0) 收藏

    APP被苹果APPStore拒绝的各种原因 1.程序有重大bug,程序不能启动,或者中途退出. 2.绕过苹果的付费渠道,我们之前游戏里的用兑换码兑换金币. 3.游戏里有实物奖励的话,一定要说清楚,奖励 ...

  4. 008_AuditionCC系列1

    一.一二章编辑音频文件. (1)在音轨编辑页面,按鼠标滚轮或键盘上的+个-号可实现Zoom in(放大),Zoom out(缩小) (2)①次声波频率在<20Hz和>20000Hz之间②人 ...

  5. List 重载添加-add,删除-remove方法,以及获取子集方法

    package seday12; import java.util.ArrayList;import java.util.List; /*** @author xingsir* List重载了一对ad ...

  6. KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解

    KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解 哦淦我已经菜到被ABC吊打了. A - Century 首先把当前年 ...

  7. BZOJ 1688: Disease Manangement (子集枚举)

    Disease Manangement Q - 枚举子集 Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d &a ...

  8. Python爬虫 - 爬取百度html代码前200行

    Python爬虫 - 爬取百度html代码前200行 - 改进版,  增加了对字符串的.strip()处理 源代码如下: # 改进版, 增加了 .strip()方法的使用 # coding=utf-8 ...

  9. BZOJ1688|二进制枚举子集| 状态压缩DP

    Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) diseases (numbered 1..D) ...

随机推荐

  1. 解决Win7&Win8 64位下Source Insight提示未完整安装的问题

    网上的破解版的注册表文件都是针对32位系统的,所以在64位系统里运行根本无法破解.下面分别贴出这俩系统里的破解文件. 使用方法: 分别复制对应系统的内容,新建文本文档,将内容粘贴进去,重命名为.reg ...

  2. IOS架构师之路:我对IOS架构的点点认识(大纲)

    1.今天我鼓起了勇气,想纪录自己对IOS架构学习成长的点点滴滴. 从事IOS开发也有几年的时间,从刚開始最主要的语言.界面.逻辑,再到后面复杂点的线程.数据处理.网络请求.动画,最后到最复杂的底层音视 ...

  3. Invalid file permission Please regenerate them with cacaoadm create-keys --force

    1.服务器重启之后,启动cacao报错,提示无效的文件权限. [root@ldapserver bin]# ./cacaoadm start Invalid file permission: [/ho ...

  4. 常用Java Web 服务器

    Java Web应用程序需要部署在Java web服务器中运行,常用的Java Web服务器有Tomcat.GlassFish.WebLogic.JBoss.WebSphere.Jetty.JRun等 ...

  5. C#运算符的优先级

    在C#中,一共有38个常用的运用符,根据它们所执行运算的特点和它们的优先级,为了便于记忆,我将它们归为七个等级:1.单元运算符和括号.2.常规算术运算符.3.位移运算符.4.比较运算符.5.逻辑运算符 ...

  6. Android Studio代码自动提示无效

    不生效的原因是因为你AS设置成了省电模式,设置成省电模式了的话,AS会禁掉一些辅助功能,达到省电的目的.所以代码自动提示也被禁掉了. 要修改回来的话,通过File选项,然后倒数第二项:Power Sa ...

  7. MVC 5 + EF 6

    (一) ??运算符 C#中两个问号(“?”)的作用是判断“?”左边的对象是否为null,如果不为null则使用“?”左边的对象,如果为null则使用“?”右边的对象. (二)VS安装Entity Fr ...

  8. SQL Server 2005为数据库设置用户名和密码的方法

    1.打开SQL Server Manager管理器,在左面找到 ‘安全性’ 单击右键 选择‘新建”->“登录”, 如下图 2.弹出对话框,在登录名中输入你的登录号,选择'SQLSERVER身份验 ...

  9. A Byte of Python 笔记(3)运算符和表达式

    第5章 运算符与表达式 大多数语句(逻辑行)都包含表达式.例子,如 2 + 3.一个表达式可以分解为运算符和操作数. 运算符 运算符 名称 说明 例子 + 加 两个对象相加 3 + 5得到8.'a' ...

  10. MYSQL 删除二进制日志的 3 个方法

    方法 1: reset master; ------------------ 删除前: 删除日志: 删除后: ----------------------------------------    可 ...