贪心+枚举/哈希表 HDOJ Trouble
题意:5个集合,每个集合最多200个数字,问是否每个集合挑一个数加起来和为0。
分析:显然n^5的程序果断超时,甚至n^3logn的二分也过不了。想n^3的方法,既然判断有没有,那么可以将两个两个的集合合并成两个大集合,再枚举最后一个集合,两个大集合排完序之后一个指针从开头最小开始,另一个从最大的开始,>0,大指针往左移,<0,小指针往右移,那么可以在线性时间求解,这贪心方法很巧妙!
另一种做法算是暴力+优化了,哈希表储存一个两个集合合并后大集合的数字,n^3暴力询问是否哈希表内存在它的相反数,哈希表用到链式前向星,总算有点理解了,贴张图:
收获:1. ”微调“贪心方法 2. 哈希表 + 链式前向星
代码1(贪心):
/************************************************
* Author :Running_Time
* Created Time :2015-8-26 9:07:01
* File Name :HDOJ_4334.cpp
************************************************/ #include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std; #define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 2e2 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
ll a[5][N];
ll sum[2][N*N]; int main(void) {
int T; scanf ("%d", &T);
while (T--) {
int n; scanf ("%d", &n);
for (int i=0; i<5; ++i) {
for (int j=0; j<n; ++j) {
scanf ("%I64d", &a[i][j]);
}
}
int tot = 0;
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
sum[0][tot] = a[0][i] + a[1][j];
sum[1][tot++] = a[2][i] + a[3][j];
}
}
sort (sum[0], sum[0]+tot);
sort (sum[1], sum[1]+tot);
int cnt1 = 1, cnt2 = 1;
for (int i=1; i<tot; ++i) { //其实离散化没什么优化
if (sum[0][i] != sum[0][i-1]) sum[0][cnt1++] = sum[0][i];
if (sum[1][i] != sum[1][i-1]) sum[1][cnt2++] = sum[1][i];
} bool flag = false;
for (int i=0; i<n && !flag; ++i) {
for (int j=0,k=cnt2-1; j<cnt1 && k>=0; ) {
ll tmp = a[4][i] + sum[0][j] + sum[1][k];
if (tmp == 0) {
flag = true; break;
}
else if (tmp < 0) j++;
else k--;
}
} printf ("%s\n", flag ? "Yes" : "No");
} return 0;
}
代码2(哈希表):
/************************************************
* Author :Running_Time
* Created Time :2015-8-26 18:21:55
* File Name :D_2.cpp
************************************************/ #include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std; #define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 2e2 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e6 + 7;
struct Hash_Table {
struct Edge {
ll x;
int nex;
}edge[MOD];
int head[MOD], E;
void init(void) {
memset (head, -1, sizeof (head));
E = 0;
}
void insert(ll x) {
int u = (x % MOD + MOD) % MOD;
for (int i=head[u]; ~i; i=edge[i].nex) {
if (edge[i].x == x) return ;
}
edge[E].x = x; edge[E].nex = head[u];
head[u] = E++;
}
bool find(ll x) {
int u = (x % MOD + MOD) % MOD;
for (int i=head[u]; ~i; i=edge[i].nex) {
if (edge[i].x == x) return true;
}
return false;
}
}ha;
ll a[5][N]; int main(void) {
int T; scanf ("%d", &T);
while (T--) {
int n; scanf ("%d", &n);
for (int i=0; i<5; ++i) {
for (int j=0; j<n; ++j) scanf ("%I64d", &a[i][j]);
}
ha.init ();
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
ha.insert (a[0][i] + a[1][j]);
}
}
bool flag = false;
for (int i=0; i<n && !flag; ++i) {
for (int j=0; j<n && !flag; ++j) {
for (int k=0; k<n; ++k) {
if (ha.find (-(a[2][i] + a[3][j] + a[4][k]))) {
flag = true; break;
}
}
}
}
puts (flag ? "Yes" : "No");
} return 0;
}
贪心+枚举/哈希表 HDOJ Trouble的更多相关文章
- 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem——哈希表&&二进制枚举
题意 有长度为 $n$($1\leq n\leq 36$)的数列,给出 $s$,求和为 $s$ 的子集,保证子集存在且唯一. 分析 答案肯定是来自左右半边两部分组成的. 如果我们用哈希表存一半,计算另 ...
- 深入理解PHP内核(六)哈希表以及PHP的哈希表实现
原文链接:http://www.orlion.ga/241/ 一.哈希表(HashTable) 大部分动态语言的实现中都使用了哈希表,哈希表是一种通过哈希函数,将特定的键映射到特定值得一种数据 结构, ...
- noip模拟赛 好元素 哈希表的第一题
这是一道关于 题2好元素 2s [问题描述] 小A一直认为,如果在一个由N个整数组成的数列{An}中,存在以下情况: Am+An+Ap = Ai (1 <= m, n, p < i < ...
- c# 哈希表跟函数
一.哈希表集合 先进后出,一个一个赋值,但只能一起取值. 1.哈希表的建立.赋值以及读取. 2.利用枚举类型打印出集合中的Key值和Value值. 二.函数 函数:能够独立完成某项功能的模块. 函数四 ...
- C#部分---特殊集合:stack栈集合、queue队列集合、哈希表集合。
1.stack栈集合:又名 干草堆集合 栈集合 特点:(1)一个一个赋值 一个一个取值(2)先进后出实例化 初始化 Stack st = new Stack(); //添加元素用push st.Pus ...
- 哈希表(hashtable)的javascript简单实现
javascript中没有像c#,java那样的哈希表(hashtable)的实现.在js中,object属性的实现就是hash表,因此只要在object上封装点方法,简单的使用obejct管理属性的 ...
- c# 哈希表集合;函数
* 哈希表集合 1.先进去的后出来,最后进去的先出来 2.利用枚举类型打印出集合中的Key值和Value值 ** 函数 1.函数:能够独立完成某项功能的模块. 函数四要素:输入.输出.函数体.函数名 ...
- Gold Balanced Lineup(哈希表)
Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10711 Accepted: 3182 Description Farm ...
- Stack集合 Queue队列集合 Hashtable哈希表
Stack集合 干草堆集合 栈集合 栈;stack,先进后出,一个一个赋值,一个一个取值,安装顺序来. 属性和方法 实例化 初始化 Stack st = new Stack(); 添加元素 个数 Co ...
随机推荐
- atomic原子操作
C++中对共享数据的存取在并发条件下可能会引起data race的未定义行为,需要限制并发程序以某种特定的顺序执行,有两种方式:1.使用mutex保护共享数据: 2.原子操作 原子操作:针对原子类型操 ...
- 运行计划中cost计算方法
概念: blevel:二元高度=索引高度-1 clustering_factor:集群因子,通过索引扫面得出的要查询table的blocks数量,clustering_factor接近table的bl ...
- 编程基础知识——Java JNI开发流程(2)
android中使用jni调用本地C++库 android平台上的本地库文件后缀 .so.类似windows上的dll文件. 要在android上使用jni.首先须要下载android ndk. 操作 ...
- MySQL基础笔记(五) 视图
一.什么是视图 视图是一个虚拟表.也就是说,视图在外观和行为上都类似于表,但它不需要实际的物理存储,只保存了视图定义(查询语句). 视图由select查询所定义 -- 当创建一个视图时,实际上是在数据 ...
- mingw在Dos下升级gnu编译器版本
在dos窗口下输入: mingw-get update mingw-get upgrade gfortran gcc g++ 强烈建议卸载后再安装新版本
- Hibernate 之 二级缓存
在上篇文章中我们对缓存以及Hibernate的一级缓存进行了介绍,接下来的主要内容将是Hibernate的二级缓存. 二级缓存也称为进程级的缓存或SessionFactory级的缓存,二级缓存可以被所 ...
- putty字体大小颜色、全屏/退出全屏快捷键 保存session设置[转]
字体大小设置 Window->Appearance->Font settings->Change按钮设置(我的设置为16)字体为(Consolas) 字体颜色设置 Window-&g ...
- Linux 下的编辑/编译器
linux 首先有两个重量级的文本编辑器:vim 和 emacs 此外有如下三种比较好的开放环境: 1.Anjuta Anjuta DevStudio 的官方地址:http://anjuta.sour ...
- 不常见使用的css
flex和white-space等属性 1.flex属性让所有弹性盒模型对象的子元素都有相同的长度,忽略它们内部的内容.style={{flex:5}},该元素占父元素的六分之五. 2. white- ...
- LeetCode 1.两数之和(JS)
Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...