1144. The Emperor's Riddle

Time limit: 1.0 second
Memory limit: 4 MB

Background

In the olden times there was a young emperor who was the bravest, wisest, richest, most handsome in the whole world. He had proven himself in endless of battles, quests, and victories but his court was not happy because he had not appointed a queen yet. However, choosing a queen was not easy because of his high status and standard, the emperor wanted a girl not only beautiful but smart and kind as well. Lightning Knight - that was the young Emperor's name - sent his most trusted knights out to seek for a girl like that; and after a long time searching, the men brought back two of the most beautiful and intelligent girls in all the lands. They were two princess sisters from a faraway land. The older sister - Van Trinh - was mysterious and beautiful like the moon, while Thuy Linh - the younger one - was bright and lovely as the sun. They were both famous for being kind, gentle, and intelligent to their people, and as many girls before them, they both fell truly, madly, deeply in love with the handsome emperor at first sight.
Now, the Emperor had to face the hardest test of all: to pick just one in these two sisters to become his rightful and beloved queen and lay the world under her feet. After countless sleepless nights, the Emperor sought out a just solution. He thought of a riddle and announced to the two princesses and the court that he would marry the first one who bring the right answer to his desk.

Problem

At the same time with the above event, the Emperor had just won the most important battle to unite all the lands in the world. That was two good news in such a short time. Being the rich and generous emperor he was, the Emperor wanted to reward to all the brave and loyal generals with boxes of gold. The distribution was not easy and that's why he chose it as the riddle for Van Trinh and Thuy Linh. Centuries has passed since then, the Emperor and queen might have died and their romance might have been forgotten from our world, but the riddle still remains as one of the hardest tasks in the ancient books.
The Emperor wants to reward N boxes of gold to M generals. The i-th box has the value of Ai. Now the Emperor wants to give N boxes to M generals so that the difference of gold between the general who receives the most gold and the general who receives the least gold is as small as possible. Note: a general can receive more than one box, and he must receive the whole box (i.e.: not half or 1/3 of box).

Input

The 1st line contains three positive integers N, M and K (N ≤ 10000, M ≤ 1000 and N ≥ M). K is the maximum result that the emperor accepts. The 2nd line contains N positive integers 0 < A1, A2, …, AN ≤ 1000.

Output

The 1st line contains one integer which is the minimum difference your program can find. In the next M lines, the i-th line contains the index of boxes rewarded to the i-th general.

Sample

input output
10 3 4
12 95 16 37 59 50 47 3 41 95
4
6 7 9 1
8 10 4 3
5 2
Problem Author: HNT 
Difficulty: 1778
 
题意:把n个数分成m组,要使极差小于k,问其中一组方案。
分析:这是一道很不错的题。
一定要注意到,这题不需要求精确解。
首先有一个显而易见的贪心。
把数字从大到小排序,然后分给目前总和最小的组。
然而这个贪心只能求得较优解,在大多数情况下,无法求得满足极差小于k的解。
 
。。。。然而有一种很不错的方法叫做调整法。。。
首先,有一个经典问题:有两组数,要让它们两两配对,使得这些数对之和的极差最小,怎么配对?
显然是一组从大到小,一组从小到大匹配。
那么回到原题。
我们先随便将n个数分成m组。
然后将每组树再随机分成两组,记为A组,B组。
然后问题就变成了经典问题:有2组m个数,要让它们两两配对,是的这些数对之和极差最小。
我们利用这种思想将A组,B组重新分配。
根据那个经典问题的思想,新的分配方案不会比旧的分配方案要差。
所以我们不断进行这一过程,直到极差不超过k。
 
实际实现的过程当中,我们可以采用贪心与调整法相结合的方法,
因为调整法毕竟调整的速度比较慢,容易超时。
 
 
 /**
Create By yzx - stupidboy
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <ctime>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef double DB;
#define MIT (2147483647)
#define INF (1000000001)
#define MLL (1000000000000000001LL)
#define sz(x) ((int) (x).size())
#define clr(x, y) memset(x, y, sizeof(x))
#define puf push_front
#define pub push_back
#define pof pop_front
#define pob pop_back
#define ft first
#define sd second
#define mk make_pair inline int Getint()
{
int Ret = ;
char Ch = ' ';
bool Flag = ;
while(!(Ch >= '' && Ch <= ''))
{
if(Ch == '-') Flag ^= ;
Ch = getchar();
}
while(Ch >= '' && Ch <= '')
{
Ret = Ret * + Ch - '';
Ch = getchar();
}
return Flag ? -Ret : Ret;
} const int N = , M = ;
int n, m, k, arr[N];
priority_queue<pair<int, int> > index, boxes;
int sum[M], belong[N], tag[N];
int tmp[N];
int type[][M], ranks[M], to[M]; inline void Input()
{
scanf("%d%d%d", &n, &m, &k);
for(int i = ; i <= n; i++) scanf("%d", &arr[i]);
} inline int Check()
{
for(int i = ; i <= m; i++) sum[i] = ;
for(int i = ; i <= n; i++) sum[belong[i]] += arr[i];
int mx = -INF, mn = INF;
for(int i = ; i <= m; i++)
mx = max(mx, sum[i]),
mn = min(mn, sum[i]);
return (mx - mn) - k;
} inline bool Compare(int t, int a, int b)
{
return type[t][a] < type[t][b];
} inline bool CmpUp(int a, int b)
{
return Compare(, a, b);
} inline bool CmpDown(int a, int b)
{
return Compare(, b, a);
} inline void Solve()
{
srand(time());
//sort(arr + 1, arr + 1 + n, greater<int>() );
for(int i = ; i <= m; i++) index.push(mk(-sum[i], i));
for(int i = ; i <= n; i++) boxes.push(mk(arr[i], i));
for(int i = ; i <= n; i++)
{
int u = index.top().sd, v = boxes.top().sd;
index.pop(), boxes.pop();
sum[u] += arr[v], belong[v] = u;
index.push(mk(-sum[u], u));
} int now;
while((now = Check()) > )
{
//printf("%d\n", now);
for(int i = ; i <= n; i++)
tag[i] = rand() & ; for(int t = ; t < ; t++)
for(int i = ; i <= m; i++)
type[t][i] = ;
for(int i = ; i <= n; i++)
type[tag[i]][belong[i]] += arr[i]; for(int t = ; t < ; t++)
{
for(int i = ; i <= m; i++)
ranks[i] = i;
if(t == )
sort(ranks + , ranks + + m, CmpUp);
else sort(ranks + , ranks + + m, CmpDown); for(int i = ; i <= m; i++) to[ranks[i]] = i;
for(int i = ; i <= n; i++)
if(tag[i] == t)
tmp[i] = to[belong[i]];
} for(int i = ; i <= n; i++)
belong[i] = tmp[i];
} int ans = Check() + k;
printf("%d\n", ans);
vector<int> answer[M];
for(int i = ; i <= n; i++) answer[belong[i]].pub(i);
for(int i = ; i <= m; i++)
{
int length = sz(answer[i]);
for(int j = ; j < length - ; j++)
printf("%d ", answer[i][j]);
if(length) printf("%d\n", answer[i].back());
/*int p = 0;
for(int j = 0; j < length - 1; j++)
{
printf("%d ", arr[answer[i][j]]);
p += arr[answer[i][j]];
}
if(length)
{
printf("%d ", arr[answer[i].back()]);
p += arr[answer[i].back()];
}
printf("%d\n", p);*/
}
//sfor(int i = 1; i <= m; i++) printf("%d ", sum[i]);
} int main()
{
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
Input();
Solve();
return ;
}

ural 1144. The Emperor's Riddle的更多相关文章

  1. URAL 1994 The Emperor's plan 求组合数 大数用log+exp处理

    URAL 1994 The Emperor's plan 求组合数 大数用log #include<functional> #include<algorithm> #inclu ...

  2. URAL 1994 The Emperor's plan

    期望$dp$. $dp[i][j]$表示第$1$种人有$i$个,第$2$种人有$j$个的情况下,到达目标状态的期望值.初始化$dp[i][0]=i$. 枚举一下这个状态死多少人,取个$max$,最后$ ...

  3. POJ 1144

    http://poj.org/problem?id=1144 题意:给你一些点,某些点直接有边,并且是无向边,求有多少个点是割点 割点:就是在图中,去掉一个点,无向图会构成多个子图,这就是割点 Tar ...

  4. 网页闯关游戏(riddle webgame)--H5刮刮卡的原理和实践

    前言: 之前编写了一个网页闯关游戏(类似Riddle Game), 除了希望大家能够体验一下我的游戏外. 也愿意分享编写这个网页游戏过程中, 学到的一些知识. 对于刮刮卡, 想必大家都很熟悉, 也很喜 ...

  5. 后缀数组 POJ 3974 Palindrome && URAL 1297 Palindrome

    题目链接 题意:求给定的字符串的最长回文子串 分析:做法是构造一个新的字符串是原字符串+反转后的原字符串(这样方便求两边回文的后缀的最长前缀),即newS = S + '$' + revS,枚举回文串 ...

  6. ural 2071. Juice Cocktails

    2071. Juice Cocktails Time limit: 1.0 secondMemory limit: 64 MB Once n Denchiks come to the bar and ...

  7. ural 2073. Log Files

    2073. Log Files Time limit: 1.0 secondMemory limit: 64 MB Nikolay has decided to become the best pro ...

  8. ural 2070. Interesting Numbers

    2070. Interesting Numbers Time limit: 2.0 secondMemory limit: 64 MB Nikolay and Asya investigate int ...

  9. ural 2069. Hard Rock

    2069. Hard Rock Time limit: 1.0 secondMemory limit: 64 MB Ilya is a frontman of the most famous rock ...

随机推荐

  1. Java中常见数据结构:list与map -底层如何实现

    1:集合 2 Collection(单列集合) 3 List(有序,可重复) 4 ArrayList 5 底层数据结构是数组,查询快,增删慢 6 线程不安全,效率高 7 Vector 8 底层数据结构 ...

  2. 三、jQuery--jQuery实践--搜索框制作

    input标签讲解 <input/>作为按钮的type属性:button.submit(后面会有二者对比分析)

  3. php PDO:数据访问抽象层

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. 几年前做家教写的C教程(之一)

    C语言学习宝典 首先让我们认识什么是C语言. C语言是一种计算机开发语言,是一种非常基础的开发语言.能够用C语言做很多事情.C语言是顺序执行的程序. 程序应该包括数据描述,数据操作. C语言的数据类型 ...

  5. 【翻译十七】java-并发之高性能对象

    High Level Concurrency Objects So far, this lesson has focused on the low-level APIs that have been ...

  6. Ultra-QuickSort【归并排序典型题目】

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 34470   Accepted: 12382 ...

  7. 华为Mate8 NFC 时好时坏,怎么解决呢?

    拿起手机朝桌子上磕几下,nfc就好用了.这是花粉总结的,我也试过,很灵.注意要带套,摄像头朝下,头部低一点往下磕.因为nfc芯片在头部,估计是接触不良.

  8. hdu 4412 2012杭州赛区网络赛 期望

    虽然dp方程很好写,就是这个期望不知道怎么求,昨晚的BC也是 题目问题抽象之后为:在一个x坐标轴上有N个点,每个点上有一个概率值,可以修M个工作站, 求怎样安排这M个工作站的位置,使得这N个点都走到工 ...

  9. Waiting Processed Cancelable ShowDialog

    namespace ConsoleApplication { using System; using System.Threading; using Microshaoft; /// <summ ...

  10. POJ 1840 Eqs 二分+map/hash

    Description Consider equations having the following form: a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0 The co ...