垃圾佬的旅游III(Hash + 暴力)

题目链接:http://120.78.128.11/Problem.jsp?pid=3445

最开始的思路就是直接暴力求解,先把所有的数值两两存入结构体,再从小到大枚举。用二分的思路去判断数值以及出现,结果TLE,但优化一下应该也能过,因为题目说只有两组数据。代码如下:

  1 #include <iostream>
  2 #include <string>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <sstream>
  6 #include <iomanip>
  7 #include <map>
  8 #include <stack>
  9 #include <deque>
 10 #include <queue>
 11 #include <vector>
 12 #include <set>
 13 #include <list>
 14 #include <cstring>
 15 #include <cctype>
 16 #include <algorithm>
 17 #include <iterator>
 18 #include <cmath>
 19 #include <bitset>
 20 #include <ctime>
 21 #include <fstream>
 22 #include <limits.h>
 23 #include <numeric>
 24
 25 using namespace std;
 26
 27 #define F first
 28 #define S second
 29 #define mian main
 30 #define ture true
 31
 32 #define MAXN 1000000+5
 33 #define MOD 1000000007
 34 #define PI (acos(-1.0))
 35 #define EPS 1e-6
 36 #define MMT(s) memset(s, 0, sizeof s)
 37 typedef unsigned long long ull;
 38 typedef long long ll;
 39 typedef double db;
 40 typedef long double ldb;
 41 typedef stringstream sstm;
 42 const int INF = 0x3f3f3f3f;
 43
 44 int n;
 45 int ans,tot;
 46 int a[1010];
 47 struct node{
 48     int x,a,b;
 49     bool operator < (const node &b) const{
 50         return x < b.x;
 51     }
 52 }q[MAXN];
 53
 54 int find_f(int x,int a,int b){
 55     int l(0),r = tot;
 56     while(l<r){
 57         int mid = (l + r) >> 1;
 58         if(q[mid].x < x)
 59             l = mid+1;
 60         else
 61             r = mid;
 62     }
 63     while(l < tot && q[l].x == x){
 64         if(q[l].a != a && q[l].b != a && q[l].a != b && q[l].b != b)
 65             break;
 66         l++;
 67     }
 68     if(q[l].x != x)
 69         return 0;
 70     return 1;
 71 }
 72
 73 int main(){
 74     ios_base::sync_with_stdio(false);
 75     cout.tie(0);
 76     cin.tie(0);
 77     while(scanf("%d",&n)!=EOF){
 78         if(!n)
 79             break;
 80         for(int i = 1; i <= n; i++)
 81             scanf("%d",&a[i]);
 82         ans = -INF;
 83         tot = 0;
 84         MMT(q);
 85         for(int i = 1; i < n; i++){
 86             for (int j = i+1; j <= n; j++){
 87                 q[tot].x = a[i] + a[j];
 88                 q[tot].a = i;
 89                 q[tot++].b = j;
 90             }
 91         }
 92         sort(q,q+tot);
 93         for(int i = 1; i <= n; i++){
 94             for(int j = 1; j <= n; j++){
 95                 if(i != j){
 96                     int t = a[i]-a[j];
 97                     if(find_f(t,i,j)){
 98                         if(a[i] > ans)
 99                             ans = a[i];
100                     }
101                 }
102             }
103         }
104         if(ans == -INF)
105             printf("No Solution\n");
106         else
107             printf("%d\n",ans);
108     }
109     return 0;
110 }

AC思路是队友告诉我的,在暴力枚举的基础上加一个Hash维护。还是记录两两的和,再枚举第三个数,但这里判断一下第三个数和答案是否在两两数和中存在就行了。判断就是每两个数标记一下,排进哈希散列表就行了。值得注意的是,哈希因为本质是同余,所以需要加一句特判,在判断存在之后,取出组成两两和的那两数,再判断三个值是否相等。

为什么要加特判 ,因为哈希是MOD 一个 P ,所以可能出现重复。

还有就是哈希MOD P而不能是任意数,开始就mod1e6+5虽然对于两组数据可能没问题,但是最好还是改成质数例如(1e6+3);

AC代码:

  1 #include <iostream>
  2 #include <string>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <sstream>
  6 #include <iomanip>
  7 #include <map>
  8 #include <stack>
  9 #include <deque>
 10 #include <queue>
 11 #include <vector>
 12 #include <set>
 13 #include <list>
 14 #include <cstring>
 15 #include <cctype>
 16 #include <algorithm>
 17 #include <iterator>
 18 #include <cmath>
 19 #include <bitset>
 20 #include <ctime>
 21 #include <fstream>
 22 #include <limits.h>
 23 #include <numeric>
 24
 25 using namespace std;
 26
 27 #define F first
 28 #define S second
 29 #define mian main
 30 #define ture true
 31
 32 #define MAXN 1000000+5
 33 #define MOD 1000000007
 34 #define PI (acos(-1.0))
 35 #define EPS 1e-6
 36 #define MMT(s) memset(s, 0, sizeof s)
 37 typedef unsigned long long ull;
 38 typedef long long ll;
 39 typedef double db;
 40 typedef long double ldb;
 41 typedef stringstream sstm;
 42 const int INF = 0x3f3f3f3f;
 43
 44 int n, a[1001], Hash[1000005],d;
 45 int MAXn = MAXN - 2;
 46 struct node{
 47     int x,a,b;
 48     bool operator < (const node &b) const{
 49         return x < b.x;
 50     }
 51 }q[MAXN];
 52
 53 int check(int tp, int a, int b){
 54     return (q[tp].a == a || q[tp].b == a || q[tp].b == a || q[tp].b == b);
 55 }
 56
 57 int main(){
 58     ios_base::sync_with_stdio(false);
 59     cout.tie(0);
 60     cin.tie(0);
 61     while(scanf("%d",&n)!=EOF){
 62         d = 0;
 63         MMT(Hash);
 64         MMT(q);
 65         for(int i = 1; i <= n; i++)
 66             scanf("%d",a+i);
 67         sort(a+1,a+1+n);
 68         for(int i = 1; i < n; i++)
 69             for(int j = i+1; j <= n; j++){
 70                 int k = (a[i]+a[j]) % MAXn;
 71                 if(k < 0) k += MAXn;
 72                 if(!Hash[k]) {
 73                     Hash[k] = ++d;
 74                     q[d].a = i, q[d].b = j;
 75                 }else{
 76                     d++;
 77                     int tp = Hash[k];
 78                     while(q[tp].x)
 79                         tp = q[tp].x;
 80                     q[tp].x = d;
 81                     q[d].a = i, q[d].b = j;
 82                 }
 83             }
 84
 85         int ans = n, flag = 1;
 86         for(; ans && flag; ans--)
 87             for(int i = n; i; i--){
 88                 if(i == ans)
 89                     continue;
 90                 int k = (a[ans]-a[i]) % MAXn;
 91                 if(k < 0)
 92                     k += MAXn;
 93                 if(!Hash[k])
 94                     continue;
 95                 int tp = Hash[k];
 96                 while(check(tp, i, ans) && q[tp].x)
 97                     tp = q[tp].x;
 98                 if(!check(tp, i, ans) && tp){
 99                     if(a[q[tp].a] + a[q[tp].b] + a[i] != a[ans]) continue;
100                     flag = 0;
101                     printf("%d\n", a[ans]);
102                     break;
103                 }
104             }
105         if(flag)
106             printf("No Solution\n");
107     }
108     return 0;
109 }

emmmm还有就是冲突处理,数组模拟一下链表就行了 =7=

这个题可能无从入手的地方就是不知道该怎么模拟,直接四个数枚举肯定炸,然后二二模拟也不行,所以就肯定需要一些手段进行维护和判断。所以就要开数组标记呀, 但肯定这么大的数开不了,那么就只好压缩数组了,这里就想到了二分去判断第三个数以及答案是否存在,但是又TLE,那就hash呗,反正处理数据的只有那么几种方法。

一些小问题就是写hash遇到负数情况,重复冲突情况以及特判。其他的话也就没什么了。

原文地址:https://www.cnblogs.com/xenny/p/9467281.html

时间: 2024-10-10 17:09:32

垃圾佬的旅游III(Hash + 暴力)的相关文章

hdu 4886 TIANKENG’s restaurant(2)(hash+暴力)

题目链接:hdu 4886 TIANKENG's restaurant(2) 题目大意:给定一个字符串S,要求在该字符串中找到一个最短并且字符串字典序最小. 解题思路:每次枚举字符串的长度,然后将S中所有该长度的子串映射成一个9进制数,最后再遍历一遍标记数组. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1000005; i

zoj 3817 Chinese Knot(hash+暴力)

题目链接:zoj 3817 Chinese Knot 题目大意:给出四个字符串,对应着同心结的四条边,现在给定一个目标串,可以从任意节点开始移动,问是否可以匹配目标串. 解题思路:用hash将四个字符串的正序和逆序处理出来,然后dfs枚举,每次保留起始位置和移动方向即可. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace st

hdu 1496 hash+暴力

http://acm.hdu.edu.cn/showproblem.php?pid=1496 Problem Description Consider equations having the following form: a*x1^2+b*x2^2+c*x3^2+d*x4^2=0 a, b, c, d are integers from the interval [-50,50] and any of them cannot be 0. It is consider a solution a

BZOJ-2081-[Poi2010]Beads(hash+暴力)

Description Zxl有一次决定制造一条项链,她以非常便宜的价格买了一长条鲜艳的珊瑚珠子,她现在也有一个机器,能把这条珠子切成很多块(子串),每块有k(k>0)个珠子,如果这条珠子的长度不是k的倍数,最后一块小于k的就不要拉(nc真浪费),保证珠子的长度为正整数. Zxl喜欢多样的项链,为她应该怎样选择数字k来尽可能得到更多的不同的子串感到好奇,子串都是可以反转的,换句话说,子串(1,2,3)和(3,2,1)是一样的.写一个程序,为Zxl决定最适合的k从而获得最多不同的子串. 例如:这一

百练2812:恼人的青蛙

传送门:http://bailian.openjudge.cn/practice/2812/ [题解] 垃圾题目毁我青春. 暴力枚举两个点,判断是否成立. 瞎jb判一判,剪剪枝就过了. 大概就是排序后如果当前x+dx已经大于n了就break (听说会快很多(并没有)) 我怎么这么傻逼啊:反正只有一条路径,只要找头两个即可,那么会省去很多时间. # include <stdio.h> # include <string.h> # include <iostream> #

NOIP 2015 DAY2

跳石头 题目背景 一年一度的“跳石头”比赛又要开始了! 题目描述 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之间,有 N 块岩石(不含起点和终 点的岩石).在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达 终点. 为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳 跃距离尽可能长.由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能 移走起点和终点的岩石). 输入输出格式

《微信公众平台入门到精通》Vol.1

<微信公众平台入门到精通>Vol.1 从今天开始微信公众平台教程开写,前面部分会比较浅,已经在玩的朋友可以忽略. 第一章    微信公众账号注册.设置.登陆 一.微信公众平台注册 注册前的准备工作,很重要! 1.一个没有注册过公众账号的邮箱,如果是qq邮箱那么对应的qq号也要没有注册过公众账号. 2.身份证扫描件,每个身份证可以注册5个公众账号 3.手机,用来接受注册验证码 4.想好公众账号名称,非常重要,一旦申请成功名称不能修改,并且该名称最好与已获得认证的腾讯微博名称相同,等公众号到500

poj 2758 &amp;&amp; BZOJ 2258 Checking the Text 文本校对

Description   为了给Wind买生日礼物,Jiajia不得不找了一份检查文本的工作.这份工作很无聊:给你一段文本 要求比对从文本中某两个位置开始能匹配的最大长度是多少.但比无聊更糟糕的是,Jiajia的经理 还可能往文本里面插入一些字符. Jiajia想用一个程序来解决这些繁琐的工作.这个程序的速度要足够快,因为Wind的生日就快要到了 Jiajia必须赚到足够多的钱,也就是处理足够多的文本. Input 输入文件第一行是原始文本. 输入文件第二行是操作数n.此后n行,每行描述一条命

[bzoj3217]ALOEXT

被这题虐了快两天............ 找最大的异或值显然用trie..因为还要支持插入删除修改..所以就用平衡树套trie. 如果旋转的话,整颗trie都要重新建,所以正常姿势是替罪羊树(虽然只是早建晚建的区别= =)? 看了学长的解题报告后才敢用treap= =..结果就陷入了无尽的调试中TAT..代码能力还是拙计...前前后后改了两天,大概得有8h+吧... 具体做法:每个treap的节点上建一颗高度为20的trie(因为数的大小<2^20),在trie中插入treap节点所在子树中的所