数集

  题目大意:给定一些数的集合,要你求出集合中满足a+b+c=d的最大的d(每个数只能用一次)

  这题有两种解法,

  第一种就是对分,把a+b的和先求出来,然后再枚举d-c,枚举的时候输入按照降序搜索就好,一旦d满足条件就是最大的了,另外判断不重复存一下位置就好,时间复杂度0(n^2*logn)

  

 #include <iostream>
#include <functional>
#include <algorithm> using namespace std; typedef long long LL_INT;
static LL_INT input[];
static pair<LL_INT, pair<int,int>>sums[ * ]; LL_INT solve(const int, const int); bool cmp(const pair<LL_INT, pair<int, int>>&x, const pair<LL_INT, pair<int, int>>&y)
{
return x.first < y.first;
} int main(void)
{
LL_INT ans;
int num_sum, sum_comb;
while (~scanf("%d", &num_sum))
{
if (num_sum == ) break;
for (int i = ; i < num_sum; i++)
scanf("%lld", &input[i]); sort(input, input + num_sum);
sum_comb = ;
for (int i = ; i < num_sum; i++)
for (int j = i + ; j < num_sum; j++)
sums[sum_comb++] = make_pair(input[i] + input[j], make_pair(i, j)); sort(sums, sums + sum_comb);
ans = solve(num_sum, sum_comb);
if (ans != INT_MAX)
printf("%lld\n", ans);
else
printf("no solution\n");
}
return EXIT_SUCCESS;
} LL_INT solve(const int num_sum, const int sum_comb)
{
int tmp[] = { , }, pos_s, pos_up;
for (int i = num_sum - ; i >= ; i--)
{
for (int j = num_sum - ; j >= ; j--)
{
if (i == j) continue;
pos_s = lower_bound(sums, sums + sum_comb, make_pair(input[i] - input[j], make_pair(, )),cmp) - sums;
pos_up = upper_bound(sums, sums + sum_comb, make_pair(input[i] - input[j], make_pair(, )),cmp) - sums; if (sums[pos_s].first == input[i] - input[j])
{
for (int k = pos_s; k < pos_up; k++)
{
if (sums[k].second.first != i && sums[k].second.first != j
&&sums[k].second.second != i && sums[k].second.second != j)
return input[i];
}
}
}
}
return (LL_INT)INT_MAX;
}

  

  剪枝了还是100+ms,太慢了,我不是很满意,去网上找了下果然有更快的做法

  其实像这种找固定数的题目都可以用散列来做,把a+b散列就好了,说实话好久没做散列我都忘记散列的那几条挺好用的公式了(貌似用书上那种散列方法效率更高),这里我就直接用链表法解决了

  参考http://www.cnblogs.com/CSU3901130321/p/4546190.html

  

 #include <iostream>
#include <algorithm>
#include <functional>
#define MOD 1001 * 1001 using namespace std; static struct _set
{
int val, num[], next;
}memmory_pool[ * ];
static int Table[ * ], input[], tp; void Hash_To_Table(const int, const int, const int);
bool Search_Table(const int, const int, const int);
int solve(const int); int main(void)
{
int num_sum, sum_comb, ans;
while (~scanf("%d", &num_sum))
{
if (num_sum == )break;
for (int i = ; i < num_sum; i++)
scanf("%d", &input[i]);
sort(input, input + num_sum);
sum_comb = num_sum*(num_sum - ) / ; tp = ; fill(Table, Table + * , -);
for (int i = ; i < num_sum; i++)
for (int j = i + ; j < num_sum; j++)
Hash_To_Table(input[i] + input[j], i, j); ans = solve(num_sum);
if (ans != INT_MAX)
printf("%d\n", ans);
else
printf("no solution\n");
}
return EXIT_SUCCESS;
} void Hash_To_Table(const int _int_value, const int i, const int j)
{
int pos = (_int_value > ? _int_value : -_int_value) % MOD;
memmory_pool[tp].val = _int_value;
memmory_pool[tp].num[] = i;
memmory_pool[tp].num[] = j;
memmory_pool[tp].next = Table[pos];
Table[pos] = tp++;
} bool Search_Table(const int _int_value, const int i, const int j)
{
int pos = (_int_value > ? _int_value : -_int_value) % MOD;
for (int k = Table[pos]; k != -; k = memmory_pool[k].next)
{
if (memmory_pool[k].val == _int_value)
{
if (memmory_pool[k].num[] != i &&memmory_pool[k].num[] != i
&&memmory_pool[k].num[] != j &&memmory_pool[k].num[] != j)
return true;
}
}
return false;
} int solve(const int num_sum)
{
for (int i = num_sum - ; i >= ; i--)
{
for (int j = num_sum - ; j >= ; j--)
{
if (i == j)continue;
if (Search_Table(input[i] - input[j], i, j))
return input[i];
}
}
return INT_MAX;
}

  

  散列法复杂度是O(N^2),非常快。

  (另外有人在讨论版说他用O(n^3*logn)的时间复杂度方法94ms做出来了,我自己试了一下,如果他储存位置下标位置是一定会溢出的,不知道他怎么做出来的,而且就算是O(N^2*logn)的算法也是要用100+ms,我对他的做法表示怀疑)。

Divide and conquer:Sumsets(POJ 2549)的更多相关文章

  1. Divide and conquer:Subset(POJ 3977)

    子序列 题目大意:给定一串数字序列,要你从中挑一定个数的数字使这些数字和绝对值最小,求出最小组合数 题目的数字最多35个,一看就是要数字枚举了,但是如果直接枚举,复杂度就是O(2^35)了,显然行不通 ...

  2. Divide and conquer:Showstopper(POJ 3484)

    Showstopper 题目大意:数据挖掘是一项很困难的事情,现在要你在一大堆数据中找出某个数重复奇数次的数(有且仅有一个),而且要你找出重复的次数. 其实我一开始是没读懂题意的...主要是我理解错o ...

  3. Divide and conquer:Garland(POJ 1759)

     挂彩灯 题目大意:就是要布场的时候需要挂彩灯,彩灯挂的高度满足: H1 = A Hi = (Hi-1 + Hi+1)/2 - 1, for all 1 < i < N HN = B Hi ...

  4. Divide and conquer:Matrix(POJ 3685)

    矩阵 题目大意:矩阵里面的元素按i*i + 100000 * i + j*j - 100000 * j + i*j填充(i是行,j是列),求最小的M个数 这一题要用到两次二分,实在是二分法的经典,主要 ...

  5. Divide and conquer:Median(POJ 3579)

        快速求两数距离的中值 题目大意:给你一个很大的数组,要你求两个数之间的距离的中值 二分法常规题,一个pos位就搞定的事情 #include <iostream> #include ...

  6. Divide and conquer:Drying(POJ 3104)

    烘干衣服 题目大意:主人公有一个烘干机,但是一次只能烘干一件衣服,每分钟失水k个单位的水量,自然烘干每分钟失水1个单位的水量(在烘干机不算自然烘干的那一个单位的水量),问你最少需要多长时间烘干衣服? ...

  7. [LeetCode] 236. Lowest Common Ancestor of a Binary Tree_ Medium tag: DFS, Divide and conquer

    Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...

  8. [LeetCode] 系统刷题4_Binary Tree & Divide and Conquer

    参考[LeetCode] questions conlusion_InOrder, PreOrder, PostOrder traversal 可以对binary tree进行遍历. 此处说明Divi ...

  9. [LeetCode] 124. Binary Tree Maximum Path Sum_ Hard tag: DFS recursive, Divide and conquer

    Given a non-empty binary tree, find the maximum path sum. For this problem, a path is defined as any ...

随机推荐

  1. [译]git config

    git config git config命令用来设置git的一些配置(包括全局配置和针对单个仓储的配置).git config命令能定义一个仓储的用户信息和用户偏好. 用法 git config u ...

  2. WCF-复合类型使用;传输图片

    一:WCF服务端 IService1.cs中: public interface IService1 { [OperationContract] [WebInvoke(Method = "P ...

  3. LUXURY 7

    A.Little Pony and Expected Maximum Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:% ...

  4. CentOS 6.5安装Apache

    1.Apache的特点 功能强大.配置简单.速度快.应用广泛.性能稳定可靠,并可做代理服务器或负载均衡来使用 2.Apache的应用场合 使用Apache运行静态HTML网页.图片(处理静态小文件能力 ...

  5. VIM使用学习笔记 : 按键说明

    VIM有三种模式: 一般模式     上下左右移动光标,删除字符或删除整行,复制粘贴 编辑模式     i I i O a A r R 进入编辑模式 命令模式     在一般模式种输入 : / ?,可 ...

  6. JQuery simpleModal插件的使用-遁地龙卷风

    (0)写在前面 jquery.simpleModal.浏览器这三者的兼容性,不仅显示在报错上,还体现在所呈现的效果不是预期上. 说一下我的环境 jquery-1.8.3.js jquery.simpl ...

  7. TCP(传输控制协议)和三次握手和四次断开

    TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机网络OSI模型中, ...

  8. iOS开发——UI基础-屏幕适配

    一.适配 1.什么是适配?适应.兼容各种不同的情况 2.移动开发中,适配的常见种类 2.1系统适配 针对不同版本的操作系统进行适配 2.2屏幕适配 针对不同大小的屏幕尺寸进行适配 二.点和像素 1.在 ...

  9. Cocos2d-x3.3RC0 Cpp-test分析之NewAudioEngineDemo(转:http://blog.csdn.net/yuxikuo_1/article/details/41081453)

    #ifndef __NewAudioEngineDemo__NewAudioEngineDemo__#define __NewAudioEngineDemo__NewAudioEngineDemo__ ...

  10. Java常见的几种排序算法-插入、选择、冒泡、快排、堆排等

    本文就是介绍一些常见的排序算法.排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排 ...