贪心+枚举/哈希表 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 ...
随机推荐
- C#:excel导入导出
资源:excelService 服务 http://download.csdn.net/detail/istend/8060501 排列问题 导出时,数字和字符的排列格式默认不一样,数字靠右,字符靠左 ...
- Android c/c++ 应用向linux 平台迁移执行
鉴于近期在minicamera (linux + FPGA) 平台上模拟 安卓系统camera流程遭遇不断升级同步的困扰.尤其是 不开放源代码后 , 应用要链接封闭动态库造成的困难.以及在sprdis ...
- HTML的DIV如何实现水平居中
内部的DIV必须有下面两行代码即可 text-align:center; margin:0 auto; 在IE6中同样可以
- Android经常使用设计模式(二)
继上一篇 Android经常使用设计模式(一)里认识了观察者.适配器.代理等三种模式,这一篇将会解说下面三种模式: 工厂模式 单例模式 命令模式 1.工厂模式(Factory Pattern) 工厂模 ...
- Java对象的创建过程
//TODO https://www.cnblogs.com/chenyangyao/p/5296807.html
- android ImageUtils 图片处理工具类
/** * 加入文字到图片.相似水印文字. * @param gContext * @param gResId * @param gText * @return */ public static Bi ...
- 配置server禁止全部非法域名 訪问自己的server
1.Apache2.4.1曾经: 第一种 直接拒绝訪问 打开 httpd.conf 文件,将一下配置追加到文件最后. #直接拒绝全部非法域名 <VirtualHost *:80> Ser ...
- Vi/Vim查找替换使用方法【转】
原文地址:http://wzgyantai.blogbus.com/logs/28117977.html vi/vim 中可以使用 :s 命令来替换字符串.该命令有很多种不同细节使用方法,可以实现复杂 ...
- wget和curl
1 curl比wget支持更多的协议 2 wget是支持递归的,而curl不支持
- JS之RegExp对象(二)
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/zkn_CS_DN_2013/article/details/24243159 RegExp对象的经常 ...