P.S.o(︶︿︶)o 唉~虽然这题方程不难,但题目长,代码长,我花了超过3小时!(>﹏<)悲伤辣么大~~~ 谨此题解惠及众人,hh。

题意:给定长度为M的一串颜色序列,和平面上的N个颜色隧道。要求以颜色序列的顺序通过颜色隧道。(隧道可多次使用,可交叉,互不相同。)问从源点到汇点依次通过颜色的最小距离。

解法:f[i][j]表示通过颜色序列前 i 个颜色,这次的第 i 个颜色的隧道选 j 的最小距离。枚举第 i-1 个颜色选的隧道为 k ,则:f[i][j] = min( f[i][j] , f[i-1][k] + dis( a[k].xx , a[k].yy , a[j].x , a[j].y) + a[j].l );

我是规定每个隧道从(x,y)到(xx,yy)通过,所以读入时存2*N个隧道,(x,y)和(xx,yy)调换。这样就可以减去大部分人分f[i][j][0] 和 f[i][j][1]的多情况分析讨论,具体优越处见代码。

 1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 #include<algorithm>
6 #include<cmath>
7 using namespace std;
8 #define M 35
9 #define N 65
10 #define C 105
11 #define INF 2e9
12
13 int m,n;
14 double xs,ys,xt,yt;
15 int q[M];
16 struct node{double x,y,xx,yy,l;int c;};
17 node a[2*N];
18 double f[2][2*N];
19
20 void ins(int id,double x,double y,double xx,double yy,int c)
21 {
22 a[id].x=x,a[id].y=y,a[id].c=c;
23 a[id].xx=xx,a[id].yy=yy;
24 a[id].l=sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
25 }
26 double mmin(double x,double y) {return x<y?x:y;}
27 double dis(double x,double y,double xx,double yy) {return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));}
28
29 int main()
30 {
31 int T,i,j,k;
32 scanf("%d",&T);
33 while (T--)
34 {
35 scanf("%lf%lf%lf%lf",&xs,&ys,&xt,&yt);
36 scanf("%d",&m);
37 for (i=1;i<=m;i++) scanf("%d",&q[i]);
38 scanf("%d",&n);
39 for (i=1;i<=n;i++)
40 {
41 double x,y,xx,yy;int c;
42 scanf("%lf%lf%lf%lf%d",&x,&y,&xx,&yy,&c);
43 ins(2*i-1,x,y,xx,yy,c),ins(2*i,xx,yy,x,y,c);
44 }
45 n*=2;
46
47 double ans=INF;
48 for (j=1;j<=n;j++)
49 {
50 if (a[j].c!=q[1]) continue;
51 f[1][j]=dis(xs,ys,a[j].x,a[j].y)+a[j].l;
52 if (m==1) ans=mmin(ans,f[1][j]+dis(a[j].xx,a[j].yy,xt,yt));//xx,yy
53 }
54 int u=1;
55 for (i=2;i<=m;i++)
56 {
57 u=1-u;
58 for (j=1;j<=n;j++)
59 {
60 f[u][j]=INF;
61 if (a[j].c!=q[i]) continue;
62 for (k=1;k<=n;k++)
63 {
64 if (a[k].c!=q[i-1]) continue;
65 f[u][j]=mmin(f[u][j],f[1-u][k]+dis(a[k].xx,a[k].yy,a[j].x,a[j].y)+a[j].l);
66 }
67 if (i==m) ans=mmin(ans,f[u][j]+dis(a[j].xx,a[j].yy,xt,yt));//xx,yy
68 }
69 }
70 printf("%.4lf\n",ans);
71 }
72 return 0;
73 }

我的方法+滚动数组

 1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 #include<cmath>
6 using namespace std;
7
8 const int N=110,M=110;
9 const double INF=(double)1e9;
10 int n,m;
11 int c[N];
12 double d[N][M][2];
13 struct node{double x,y;};
14 struct edge{node s,d;double len;int c;}a[N];
15 double minn(double x,double y){return x<y ? x:y;}
16 double dist(node t1,node t2){
17 return sqrt((t1.x-t2.x)*(t1.x-t2.x)+(t1.y-t2.y)*(t1.y-t2.y));
18 }
19
20 int main()
21 {
22 int T;
23 scanf("%d",&T);
24 while(T--)
25 {
26 node st,ed;
27 scanf("%lf%lf%lf%lf",&st.x,&st.y,&ed.x,&ed.y);
28 scanf("%d",&n);
29 for(int i=1;i<=n;i++)
30 scanf("%d",&c[i]);
31 scanf("%d",&m);
32 for(int i=1;i<=m;i++)
33 {
34 scanf("%lf%lf%lf%lf%d",&a[i].s.x,&a[i].s.y,&a[i].d.x,&a[i].d.y,&a[i].c);
35 a[i].len=dist(a[i].s,a[i].d);
36 }
37 double mn=INF;
38 for(int i=1;i<=m;i++)
39 {
40 if(a[i].c==c[1])
41 {
42 d[1][i][0]=dist(st,a[i].s)+a[i].len;
43 d[1][i][1]=dist(st,a[i].d)+a[i].len;
44 if(n==1) mn=minn(mn,minn(d[1][i][0]+dist(a[i].d,ed),d[1][i][1]+dist(a[i].s,ed)));
45 }
46 }
47 for(int i=2;i<=n;i++)
48 {
49 for(int j=1;j<=m;j++)
50 {
51 d[i][j][0]=d[i][j][1]=INF;
52 if(a[j].c!=c[i]) continue;
53 for(int k=1;k<=m;k++)
54 {
55 if(a[k].c!=c[i-1]) continue;
56 d[i][j][0]=minn(d[i][j][0],a[j].len+minn(d[i-1][k][0]+dist(a[k].d,a[j].s),d[i-1][k][1]+dist(a[k].s,a[j].s)));
57 d[i][j][1]=minn(d[i][j][1],a[j].len+minn(d[i-1][k][0]+dist(a[k].d,a[j].d),d[i-1][k][1]+dist(a[k].s,a[j].d)));
58 // printf("%d %d d1 = %.3lf d2 = %.3lf\n",i,j,d[i][j][0],d[i][j][1]);
59 }
60 if(i==n) mn=minn(mn,minn(d[i][j][0],d[i][j][1]));//dist(a[j].d,ed)dist(a[j].s,ed)
61 }
62 }
63 printf("%.4lf\n",mn);
64 }
65 return 0;
66 }

他人的方法(from gyw)

P.S.而且我他人的方法我选的还是很简短的代码,我看oj上大部分人都是2千多Byte的。这2个代码是1千5、6百多Byte。

而我还打了另外一个PG,将颜色隧道按颜色排序了,j和k的循环量比原来的2*N减少了,但是由于排序是O(n log n),N的数据范围也只是几十,所以这个反而速度慢一点。另外。。这个程序只拿了5分,我不知道为何WA,求助啊!●o●

 1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 #include<algorithm>
6 #include<cmath>
7 using namespace std;
8 #define M 35
9 #define N 65
10 #define C 105
11 #define INF 2e9
12
13 int m,n;
14 double xs,ys,xt,yt;
15 int q[M],s[C];
16 struct node{double x,y,xx,yy,l;int c;};
17 node a[2*N];
18 double f[2][2*N];
19
20 void ins(int id,double x,double y,double xx,double yy,int c)
21 {
22 a[id].x=x,a[id].y=y,a[id].c=c;
23 a[id].xx=xx,a[id].yy=yy;
24 a[id].l=sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
25 }
26 bool cmp(node x,node y) {return x.c<y.c;}
27 double mmin(double x,double y) {return x<y?x:y;}
28 double dis(double x,double y,double xx,double yy) {return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));}
29
30 int main()
31 {
32 int T,i,j,k;
33 scanf("%d",&T);
34 while (T--)
35 {
36 scanf("%lf%lf%lf%lf",&xs,&ys,&xt,&yt);
37 scanf("%d",&m);
38 for (i=1;i<=m;i++) scanf("%d",&q[i]);
39 scanf("%d",&n);
40 for (i=1;i<=n;i++)
41 {
42 double x,y,xx,yy;int c;
43 scanf("%lf%lf%lf%lf%d",&x,&y,&xx,&yy,&c);
44 ins(2*i-1,x,y,xx,yy,c),ins(2*i,xx,yy,x,y,c);
45 }
46 n*=2;
47 sort(a+1,a+1+n,cmp);
48
49 int c,cc;
50 c=s[0]=a[0].c=0;
51 for (i=1;i<=n;i++)
52 if (a[i].c!=a[i-1].c)
53 {
54 while (c<a[i].c) s[++c]=i-1;
55 s[a[i].c]=i;
56 }
57 s[a[n].c+1]=n+1;
58
59 double ans=INF;
60 q[0]=0,q[m+1]=a[n].c+1;
61 ins(0,xs,ys,xs,ys,0),ins(n+1,xt,yt,xt,yt,a[n].c+1);
62 s[a[n].c+2]=n+2;
63 f[0][0]=0.0;
64
65 int u=1;
66 for (i=1;i<=m+1;i++)
67 {
68 c=q[i],cc=q[i-1];
69 for (j=s[c];j<s[c+1];j++)
70 {
71 f[u][j]=INF;
72 for (k=s[cc];k<s[cc+1];k++)
73 f[u][j]=mmin(f[u][j],f[1-u][k]+dis(a[k].xx,a[k].yy,a[j].x,a[j].y)+a[j].l);
74 if (i==m+1) ans=mmin(ans,f[u][j]);
75 }
76 u=1-u;
77 }
78 printf("%.4lf\n",ans);
79 }
80 return 0;
81 }

排序+滚动数组(WA)

【noi 2.6_687】Color Tunnels(DP)的更多相关文章

  1. 【noi 2.6_162】Post Office(DP)

    这题和"山区建小学"除了输入不同,其他都一样.(解析可见我的上一篇随笔) 但是,这次我对dis[][]加了一个优化,画一下图就可明白. 1 #include<cstdio&g ...

  2. 【noi 2.6_1481】Maximum sum(DP)

    题意:求不重叠的2段连续和的最大值. 状态定义f[i]为必选a[i]的最大连续和,mxu[i],mxv[i]分别为前缀和后缀的最大连续和. 注意:初始化f[]为0,而max值为-INF.要看好数据范围 ...

  3. 【noi 2.6_3531】判断整除(DP)

    题意:给一个正整数数列,可将其相加或相减,问是否有一个结果能被K整除. 解法:似上一题"糖果"的状态定义,f[i][j]表示是否有一个选了前 i 个数的结果模K余j. P.S. 可 ...

  4. 【noi 2.6_9271】奶牛散步(DP)

    这题与前面的"踩方格"重复了,而且是大坑题!题目漏写了取模12345的条件! 详细解析请见我之前的博文--http://www.cnblogs.com/konjak/p/59368 ...

  5. 【noi 2.6_7113】Charm Bracelet(DP)

    题意:N个饰物,有重量和渴望程度.问在M的重量限制内能达到的最大的渴望度. 解法:经典的01问题,但有一个小技巧值得记住:用if比较大小比调用max函数快了不少,这题有100ms左右. 1 #incl ...

  6. 【noi 2.6_2421】Exchange Rates(DP)

    题意:起始有1000元美元,给出N天美元与加拿大元的汇率.问N天内可以不停的兑换,每次兑换需要收取3%的手续费,问可以得到的最大的美元数. 解法:直接用2个变量存第 i 天时手中是美元和加拿大元的最大 ...

  7. 【noi 2.6_6049】买书(DP)

    题意:有N元,有无限多本10.20.50和100元的书,问有几种购买方案. 解法:f[i]表示用 i 元的方案数.还有一个 j 循环这次买多少元的书. 注意--要先 j 循环,再 i 循环.因为要先考 ...

  8. 【noi 2.6_6045】开餐馆(DP)

    题意:有N个地址,从中选一些开餐馆,要保证相邻餐馆的距离大于k.问最大利润. 解法:f[i]表示在前 i 个地址中选的最大利润. 1 #include<cstdio> 2 #include ...

  9. 【noi 2.6_4982】踩方格(DP)

    题意:一个无限大的方格矩阵,能向北.东.西三个方向走.问走N步共有多少种不同的方案. 解法: f[i]表示走 i 格的方案数. 状态转移方程推导如下--设l[i],r[i],u[i]分别为第 i 步向 ...

随机推荐

  1. Go GRPC 入门(二)

    前言 最近较忙,其实准备一篇搞定的 中途有事,只能隔了一天再写 正文 pb.go 需要注意的是,在本个 demo 中,客户端与服务端都是 Golang,所以在客户端与服务端都公用一个 pb.go 模板 ...

  2. 【C++】《C++ Primer 》第十七章

    第十七章 标准库特殊设施 一.tuple类型 tuple是类似pair的模板,每个pair的成员类型都不相同,但每个pair都恰好有两个成员. 不同的tuple类型的成员类型也不相同,一个tuple可 ...

  3. 【Sphinx】 为Python自动生成文档

    sphinx 前言 Sphinx是一个可以用于Python的自动文档生成工具,可以自动的把docstring转换为文档,并支持多种输出格式包括html,latex,pdf等 开始 建一个存放文档的do ...

  4. GMT UTC CST ISO 夏令时 时间戳,都是些什么鬼?

    目录 ✍前言 本文提纲 版本约定 ✍正文 GMT:格林威治时间 凭什么格林威治作为标准时间? 地球自转 中国有哪几个时区? 美国有哪几个时区? GMT和Http协议的渊源 UTC:世界标准时间 UTC ...

  5. Windows程序通用自动更新模块(C#,.NET4.5以上)

    本通用自动更新模块适合所有Windows桌面程序的自动更新,不论语言,无论Winform还是wpf. 一.工作流程:1. 主程序A调起升级程序B2. B从服务器获取更新程序列表,打印更新信息.3. B ...

  6. 爬虫学习(三)Chrome浏览器使用

    一.新建隐身窗口 在打开隐身窗口的时候,第一次请求某个网站是没有携带cookie的,和代码请求一个网站一样,不携带cookie.这样就能够尽可能的理解代码请求某个网站的结果:除非数据是通过js加载出来 ...

  7. guava eventbus 原理+源码分析

    前言: guava提供的eventbus可以很方便的处理一对多的事件问题, 最近正好使用到了,做个小结,使用的demo网上已经很多了,不再赘述,本文主要是源码分析+使用注意点+新老版本eventbus ...

  8. SQL 语法速成手册

    本文针对关系型数据库的一般语法.限于篇幅,本文侧重说明用法,不会展开讲解特性.原理. 一.基本概念 数据库术语 数据库(database) - 保存有组织的数据的容器(通常是一个文件或一组文件). 数 ...

  9. OAuth2.0是干什么的?

    OAuth2.0是干什么的? 首先用户有一些数据: 将数据存储在服务器上: 这时候有一个应用要访问数据: 如果这个应用是一个恶意程序呢?所以需要一个检验来判断请求是不是安全的: 如何判断是不是安全的? ...

  10. 列出HBASE所有表的相关信息,如表名、创建时间等。

    import java.io.IOException; import java.util.Collection; import java.util.Iterator; import org.apach ...