hdu 4281 Judges' response(多旅行商&DP)
Judges' response
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 454 Accepted Submission(s): 256
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.
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)
If it's impossible to serve all the contestants, please output -1 -1 instead.
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
2 8
-1 -1
8 467
题意:
给定n个地点的坐标和每个地点的权值,点有点权边有边权。现在裁判在点1,需要分配这些裁判到这些点去,已知每个裁判能够到点权之和不大于m,而且一个点不能由两个裁判访问。现在给出两个问题,1、最少几个裁判可以覆盖所有点 2、给定无数个裁判,怎么样访问这些点使得总边权和最小,裁判访问完必须回到1点,而且一个裁判访问的点权之和不能超过m。
思路:
第一个问题很简单。由于有问题的人最多16个。可以把一个裁判可以解决的问题壮压。对应位置为1表示该裁判会解决对应问题。然后这就抽象成一个物品了。然后背出全为1的状态就行了。比赛时就因为第一问简单就傻乎乎的写了。看懂第二问时就凌乱了。于是参考了下大神的博客,才知道那是MTSP(多旅行商问题)。不过用DP的方法极限数据时用了12s。。。只能说题目数据太水了。。。不过第二问的思路蛮经典的。又一次进行了抽象。把一个裁判从解决完问题到回到1点的最短用时抽象为一个物品。然后一样的背包。对于最短用时可以壮压DP求出。
详细见代码:
#include<algorithm>
#include<iostream>
#include<string.h>
#include<sstream>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<string>
#include<time.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=100010;
int n,m,cnt,ans1,ans2,lim;
int x[20],y[20],c[20];
int state[1<<17];//存可行状态
int dp[1<<17],dis[20][20];//dp处理最少的裁判数
int dpp[20][1<<17],mind[1<<17];//dpp[i][j]表示当前在i点。访问状态为j时的最小距离。
//clock_t st,ed; //mind[i]表示完成访问状态i所走的最少路程
//double dur;
bool isok(int st)//判断一个裁判的可行状态。抽象为一个物品。
{
int i=0,sum=0; while(st)
{
if(st&1)
sum+=c[i];
st>>=1;
i++;
}
if(sum<=m)
return true;
else
return false;
}
void getDist()//求距离
{
int i,j,xx,yy;
for(i=0;i<n;i++)
{
dis[i][i]=0;
for(j=i+1;j<n;j++)
{
xx=x[j]-x[i];
yy=y[j]-y[i];
dis[i][j]=dis[j][i]=ceil(sqrt((double)(xx*xx+yy*yy)));
}
}
}
void TSP()//典型的单旅行商问题
{
int s,j,ns;
memset(dp,0x3f,sizeof dp);
dp[0]=0;
for(s=0;s<lim;s++)
{
if(dp[s]==INF)
continue;
for(j=0;j<cnt;j++)
{
if(s&state[j])
continue;
ns=s|state[j];
dp[ns]=min(dp[ns],dp[s]+1);
}
}
ans1=dp[lim-1];
}
void MTSP()//多旅行商
{
int i,j,k,s,ns;
getDist();
memset(dpp,0x3f,sizeof dpp);
memset(mind,0x3f,sizeof mind);
dpp[0][1]=0;//0必须为起点
for(i=0;i<cnt;i++)
{
s=state[i];
for(j=0;j<n;j++)
{
if(s&(1<<j)&&dpp[j][s]!=INF)//枚举起点
{
mind[s]=min(mind[s],dpp[j][s]+dis[j][0]);//把一个裁判完成访问状态再回到0点抽象为一个物品
for(k=0;k<n;k++)
{
if(s&(1<<k))
continue;
ns=s|(1<<k);//ns状态不一定有效
dpp[k][ns]=min(dpp[k][ns],dpp[j][s]+dis[j][k]);
}
}
}
}
for(s=1;s<lim;s++)//大神的方法。感觉(s-1)&比较巧妙。得到的状态一定是1比s少的状态。
{
if(s&1) //递推就是从1少的状态推1多的状态
{
for(ns=(s-1)&s;ns;ns=(ns-1)&s)
mind[s]=min(mind[s],mind[ns|1]+mind[(s-ns)|1]);
}
}
/*这是我的DP方法极限数据18s。。汗。。
for(s=0;s<lim;s++)//把抽象后的物品直接背包
{
if(mind[s]==INF)//由于mind原本的值不会影响后面结果。所以不用初始化
continue;
for(i=0;i<cnt;i++)
{
if(state[i]&1)
{
if((s-1)&(state[i]-1))
continue;
ns=s|state[i];
mind[ns]=min(mind[ns],mind[s]+mind[state[i]]);
}
}
}
*/
ans2=mind[lim-1];
}
int main()
{
int i,ma; while(~scanf("%d%d",&n,&m))
{
for(i=0;i<n;i++)
scanf("%d%d",&x[i],&y[i]);
ma=0;
for(i=0;i<n;i++)
{
scanf("%d",&c[i]);
ma=max(ma,c[i]);
}
if(ma>m)
{
printf("-1 -1\n");
continue;
}
//st=clock();
cnt=0,lim=1<<n;
for(i=0;i<lim;i++)
if(isok(i))
state[cnt++]=i;
TSP();
MTSP();
//ed=clock();
//dur=(double)(ed-st)/CLOCKS_PER_SEC;
//printf("time: %.2lf\n",dur);
printf("%d %d\n",ans1,ans2);
}
return 0;
}
/*
3 3
0 0
0 3
0 4
0
2
2
3 2
0 0
0 3
1 0
0
1
2
3 1
0 0
0 3
0 1
0
1
2
4 9
1 2
1 3
2 1
3 1
0
5
6
4
16 3500
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 output:
2 14
2 8
-1 -1
2 11
1 164
*/
hdu 4281 Judges' response(多旅行商&DP)的更多相关文章
- HDU 4281 Judges' response 状压dp+多旅行商问题
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4281 Judges' response Time Limit: 2000/1000 MS (Java ...
- UVA 1347 Tour 【双调旅行商/DP】
John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane and starts vi ...
- 洛谷P1523 旅行商简化版(DP)
题目: P1523 旅行商简化版 解析 可以看做是两个人同时从西往东走,经过不一样的点,走到最东头的方案数 设\(f[i][j]\)表示一个人走到i,一个人走到j的最短距离(\(i<j\)) 第 ...
- vijosP1014 旅行商简化版
vijosP1014 旅行商简化版 链接:https://vijos.org/p/1014 [思路] 双线DP. 设ab,ab同时走.用d[i][j]表示ab所处结点i.j,且定义i>j,则有转 ...
- Bzoj3352 [ioi2009]旅行商
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 89 Solved: 36 Description 旅行商认定如何优化旅行路线是一个非常棘手的计算问题 ...
- HDU 4281 (状态压缩+背包+MTSP)
Judges' response Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- P1523 旅行商简化版
P1523 旅行商简化版 题目背景 欧几里德旅行商(Euclidean Traveling Salesman)问题也就是货郎担问题一直是困扰全世界数学家.计算机学家的著名问题.现有的算法都没有办法在确 ...
- 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法
若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...
- 洛谷P1782 旅行商的背包[多重背包]
题目描述 小S坚信任何问题都可以在多项式时间内解决,于是他准备亲自去当一回旅行商.在出发之前,他购进了一些物品.这些物品共有n种,第i种体积为Vi,价值为Wi,共有Di件.他的背包体积是C.怎样装才能 ...
随机推荐
- XP IE8 安装失败
装完XP后,此时是IE6.装了QQ浏览器,提示会锁定浏览器主页,没怎么在意. 然后装IE8时,提示失败. 在网上搜索了下是其它浏览器或程序锁定了浏览器主页.卸载QQ浏览器后,成功安装IE8.
- 手淘flexible.js框架使用和源代码讲解
手淘框架是一个用来适配移动端的js框架,下面我们来讲解一下如何使用手淘的这套框架. 其实手淘框架的核心原理就是根据不同的width给网页中html跟节点设置不同的font-size,然后所有的距离大小 ...
- 黄聪:V2010中C#实现友好的等待任务完成时,出现的多线程悬浮窗体
实现效果如下: 项目已经打包后,大家直接下载吧:[HCWaitForm.rar]
- Spark系列(二) Spark Shell各种操作及详细说明
并行化scala集合(Parallelize) //加载数据1~10 val num=sc.parallelize(1 to 10) //每个数据项乘以2,注意 _*2记为一个函数(fun) val ...
- pythonNetday06
进程 Process(target,name,args,kwargs) p.pid : 创建的新的进程的PID号 p.is_alive() 判断进程是否处于alive状态 p.daemon = Tru ...
- java 工具类 static
http://wenwen.sogou.com/z/q526955586.htm 工具类其实就是提供了一些公共的函数,方便其他类去调用,函数都写成static一方面是因为方便,另一方面是工具类的函数是 ...
- 如何更改Windows10的计算机基本信息
请问如何去掉红色框内的内容?优化大师更改无效! 最佳答案 打开注册表,定位到如下路径 1 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Current ...
- leetcode814
class Solution { public: TreeNode* pruneTree(TreeNode* root) { if(root==NULL) { return nullptr; } if ...
- 如何量化考核技术人的 KPI?
如何量化考核技术人的 KPI? 原创: 张建飞 阿里技术今天 阿里妹导读:对技术人来说,技术是成长的"核心".然而,在实际工作协作中,技术的重要性常常被业务所掩盖,造成先业务后技术 ...
- 搭建 redis 集群 (redis-cluster)
一 所需软件:Redis.Ruby语言运行环境.Redis的Ruby驱动redis-xxxx.gem.创建Redis集群的工具redis-trib.rb 二 安装配置redis redis下载地址 ...