Judges' response

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 741    Accepted Submission(s): 429

Problem Description
  The contest is running and the judges is busy watching the progress of the contest. Suddenly, N - 1 (N <= 16) contestants hand up their hand at the same time. The judges should go to answer the contestants' question one by one. The judges already foresee that answering contest i's question would cost Ci minutes. In order to serve all the contestant, each judges is assigned to serve some subset of the contestants. As the judges have limited patience, each one of them can serve the contestants for no more than M minutes.
  You are asked to solve two problems:
  1. At least how many judges should be sent so that they can serve all the contestants? (Because the judges have limited patience, each one of them cannot serve too many contestants.)
  2. If there are infinite number of judges, how to assign the route for each judge so that the sum of their walking time is minimized? Each contestant i is reside in place (xi, yi), the judges are in place (x1, y1). Assuming the walking speed of the judge is 1.
 
Input
  There are several test cases, Each case begin with two integer N, M(with the meaning in the above context, 2 <= N <= 16, 0 <= M <= 100000).
  Then N lines follow and line i will contain two numbers x, y(0 <= x, y <= 1000), indicating the coordinate of place i.
  Then another N lines follow and line i will contain numbers Ci(0 <= Ci <= 1000), indicating the time to solve contestant i's question. C1 will 0 as place 1 is for the judges.
  
  The distance between place i and place j is defined as ceil(sqrt((xi - xj) ^ 2 + (yi - yj) ^ 2)). (ceil means rounding the number up, e.g. ceil(4.1) = 5)
 
Output
  For each case, output two numbers. The first is the minimum number of judges for question 1. The second is the minimum sum of walking time for question 2.
  If it's impossible to serve all the contestants, please output -1 -1 instead.
 
Sample Input
3 3
0 0
0 3
0 1
0
1
2

3 2
0 0
0 3
0 1
0
1
2

3 1
0 0
0 3
0 1
0
1
2
  
16 35
30 40
37 52
49 49
52 64
31 62
52 33
42 41
52 41
57 58
62 42
42 57
27 68
43 67
58 48
58 27
37 69
0
19
30
16
23
11
31
15
28
8
8
7
14
6
19
11

 
Sample Output
1 6 2 8 -1 -1 8 467

题意:

  第一问:n-1个人有问题需要裁判答复、每个人需要Ci的时间、每个裁判最多回答M时间的问题、问最小需要几个裁判。

  第二问:每个人有个位置、所有裁判都在一个位置、问所有裁判回答完问题并回到原点加起来走过的距离最小是多少。

  第一问和第二问是独立的,不一定在最少裁判的基础上来走。

解题:

  第一问就是一个带有状态的01背包。

  第二问是多旅行商问题(MTSP)。

AC代码:

/** @xigua */
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
#include<deque>
#include<queue>
#include<set>
#include<string>
#include<map>
#include<climits>
#define inf LLONG_MAX
#define INF 9e7+5
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 1e2 + 5;
const ll mod = 3e12 + 7;
const db eps = 1e-9;
int n, m, x[maxn], y[maxn], c[maxn];
int dis[maxn][maxn], dp[1<<16];
int sta[1<<16], len, best[1<<16], en[16][1<<16]; //en的第二维代表状态,比如en[j][i]代表在i状态下以j结尾的最小距离
bool xx[1<<16]; int get_dis(int x1, int x2, int y1, int y2) {
return ceil(sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)));
} void init() {
memset(xx, 0, sizeof(xx));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) dis[i][j] = get_dis(x[i], x[j], y[i], y[j]);
for (int i = 0; i < (1<<n); i++) {
best[i] = INF;
dp[i] = INF;
for (int j = 0; j < n; j++)
en[j][i] = INF;
}
en[0][1] = best[0] = len = dp[0] = 0;
} bool ok(int x) {//判断当前状态能否由一个裁判回答完
int sum = 0;
for (int i = 0; i < n; i++) {
if (x&(1<<i))
sum += c[i];
}
return m >= sum;
} void get_sta() {
for (int i = 0; i < (1<<n); i++) {
if (ok(i))
sta[++len] = i, xx[i] = 1;
}
} int solve_bag() {
for (int i = 1; i <= len; i++) {
for (int j = (1<<n) - 1; j >= 0; j--) {
if (!(sta[i] & j)) {
dp[sta[i]|j] = min(dp[sta[i]|j], dp[j] + 1);
}
}
}
return dp[(1<<n)-1] == INF ? -1 : dp[(1<<n)-1];
} int solve_dd() {
for (int i = 0; i < (1<<n); i++) {
if (xx[i]) {
for (int j = 0; j < n; j++) {
if (i&(1<<j)) {
best[i] = min(best[i], en[j][i] + dis[j][0]);
for (int k = 0; k < n; k++) {
if (!(i&(1<<k))) {
en[k][i|(1<<k)] = min(en[k][i|(1<<k)], en[j][i] + dis[j][k]);
}
}
}
}
}
}
for (int i = 1; i < (1<<n); i++)
if (i&1)
for (int j = i&(i-1); j; j = i&(j-1)) //枚举比当前低的每个状态
best[i] = min(best[i], best[(i-j)|1] + best[j|1]);
return best[(1<<n)-1];
} void solve() {
while (cin >> n >> m) {
for (int i = 0; i < n; i++) cin >> x[i] >> y[i];
for (int i = 0; i < n; i++) cin >> c[i];
init();
get_sta();
int ans1= solve_bag();
if (ans1 == -1) cout << "-1 -1\n";
else cout << ans1 << ' ' << solve_dd() << endl;
}
} int main() {
//cin.sync_with_stdio(false);
//freopen("tt.txt", "r", stdin);
//freopen("hh.txt", "w", stdout);
int t = 1;
//cin >> t;
while (t--) {
solve();
} return 0;
}

  

HDU 4281 (状态压缩+背包+MTSP)的更多相关文章

  1. HDU 4739 Zhuge Liang's Mines (状态压缩+背包DP)

    题意 给定平面直角坐标系内的N(N <= 20)个点,每四个点构成一个正方形可以消去,问最多可以消去几个点. 思路 比赛的时候暴力dfs+O(n^4)枚举写过了--无意间看到有题解用状压DP(这 ...

  2. HDU 1074 (状态压缩DP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074 题目大意:有N个作业(N<=15),每个作业需耗时,有一个截止期限.超期多少天就要扣多少 ...

  3. hdu 4739(状态压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4739 思路:状态压缩. #include<iostream> #include<cs ...

  4. HDU 3341 状态压缩DP+AC自动机

    题目大意: 调整基因的顺序,希望使得最后得到的基因包含有最多的匹配串基因,使得所能达到的智商最高 这里很明显要用状态压缩当前AC自动机上点使用了基因的情况所能达到的最优状态 我最开始对于状态的保存是, ...

  5. hdu 2167(状态压缩基础题)

    题意:给你一个矩阵,让你在矩阵中找一些元素使它们加起来和最大,但是当你使用某一个元素时,那么这个元素周围的其它八个元素都不能取! 分析:这是一道比较基础的状态压缩题,也是我做的第三道状态压缩的题,但是 ...

  6. hdu 1565(状态压缩基础题)

    题意:容易理解. 分析:这是我做的状态压缩第二题,一开始超内存了,因为数组开大了,后来超时了,因为能够成立的状态就那么多,所以你应该先把它抽出来!!总的来说还是比较简单的!! 代码实现: #inclu ...

  7. HDU 2553 状态压缩

    N皇后问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  8. hdu 3006(状态压缩)

    The Number of set Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  9. hdu 2489(状态压缩+最小生成树)

    Minimal Ratio Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

随机推荐

  1. 【POI 2006】 Tet-Tetris-3D

    [题目链接] 点击打开链接 [算法] 二维线段树(树套树) 注意标记永久化 [代码] #include<bits/stdc++.h> using namespace std; #defin ...

  2. 【BZOJ 2721】 樱花

    [题目链接] 点击打开链接 [算法] 令n!=z,因为1 / x + 1 / y = 1 / z,所以x,y>z,不妨令y = z + d 则1 / x + 1 / (z + d) = 1 / ...

  3. Android适合组件化开发的路由框架:Launch

    1.概述 最近越来越不想写代码了,特别是一些重复性的代码,比如由于每次启动一个 Activity,我们都会很习惯的在 Activity 中写下: public static void launch(A ...

  4. Java调用外部类定义的方法(Static与无Static两种)

    首先定义方法 public class Dy { public int Add(int x,int y){ //定义Add(),该方法没有被static修饰 return x+y; } public ...

  5. Cocos2d-x 3.2 创建新应用

    1.cd 到 Cocos2d-x 3.2 的目录: 2.python setup.py: 3.source /Users/netty/.bash_profile ; 4.cocos new TestP ...

  6. Apache Thrift 在Windows下的安装与开发

    Windows下安装Thrift框架的教程很多.本文的不同之处在于,不借助Cygwin或者MinGW,只用VS2010,和Thrift官网下载的源文件,安装Thrift并使用. 先从官网 下载这两个文 ...

  7. Codeforces Round #364 (Div. 2)【A,C】

    啊啊啊啊啊啊啊啊啊,目睹A->CⅠA全过,最终fstwaA,C;23333333 A题: 题意: 就是分成相等的m堆,每堆有两个位置上的值相加. 思路: fst在sum可能不是偶数,先*2/n; ...

  8. jzoj5980. 【WC2019模拟12.27】字符串游戏

    首先发现双方可以有一个默契,不管谁刻意,都可以把串变为诸如\(...101010101...\)的形式 所以先手要赢的话就是要在上面的基础之上加一个字符使其变为要求的子串 那么就是要求的子串中相邻两个 ...

  9. 前端开发常用cmd命令

    windows打开命令行 开始->运行->键入cmd 也可通过附件查找到命令提示符,右键属性为其设置快捷键 快捷键 更改路径 d:        // 切换到d盘 cd  <fold ...

  10. 五个demo案例带你学习PHP反序列化漏洞

    一直想研究下php反序列化漏洞,花了几天时间做了个简单的了解..写篇文章记录下. 直白点就是围绕着serialize和unserialize两个函数. 一个用于序列化,一个用于反序列化. 我们通常把字 ...