BNU Training 2016.07.15 总结
来源:互联网 发布:js数组冒泡排序 编辑:程序博客网 时间:2024/06/10 23:54
比赛链接 https://acm.bnu.edu.cn/v3/contest_show.php?cid=8010#info
AC 8/10 ,还好=、=
简单总结一下:
A题
就是一个水题,但为什么WA了这么多次呢…
题意没读懂啊!!!
B,D,E题
一水而过,不用说
F题
题意为x * y的棋盘放k个互不攻击的国王有几种方案,答案%1000000007,T组数据。
数据规模
0 < T <= 50
2 <= x,y <= 15
1 <= k <= x*y
一看就是状压dp嘛,不过我写的比较挫,代码也比较丑,时间还慢….
f[i][j][k] 前i行放j个国王,且第i行国王摆放状态为第k个合法状态下的方案数
转移简单粗暴
其实时间上应该是A不了的,但是加了个if就过了==
n * m的棋盘最多只能放 ((n+1)/2)*((m+1)/2) 个国王…超过了直接就是0了呗。。。
应该学学q神的姿势…
#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<vector>#include<cmath>using namespace std;const int mod=1e9+7;const int maxn=1700;int p[maxn],num[maxn],cnt;int n,m,king;int maxm;int f[16][15*15+1][maxn];vector<int> v[maxn];int calc(int x){ int ans=0; while(x) { ans++; x-=x&(-x); } return ans;}inline bool ok(int x,int y){ if(p[x]&p[y]) return false; if((p[x]&(p[y]>>1)) || ((p[x]&(p[y]<<1)))) return false; return true;}int Maxking(int x,int y){ return ((x+1)/2)*((y+1)/2);}int main(){ int sk; scanf("%d",&sk); maxm=1<<15; cnt=0; for(int mask=0; mask<maxm; mask++) { if((mask&(mask>>1))==0) { p[cnt]=mask; num[cnt++]=calc(mask); } } for(int i=0;i<cnt;i++) for(int j=0;j<cnt;j++) if(ok(i,j)) v[i].push_back(j); while(sk--) { scanf("%d%d%d",&n,&m,&king); if(king>Maxking(n,m)) { printf("0\n"); continue; } maxm=1<<m; memset(f,0,sizeof(f)); f[0][0][0]=1; for(int i=1; i<=n; i++) for(int j=0; j<=king; j++) for(int k=0; p[k]<maxm; k++) for(int o=0,sz=v[k].size();o<sz;o++) if(num[k]+num[v[k][o]]<=j) { f[i][j][k]=(f[i][j][k]+f[i-1][j-num[k]][v[k][o]])%mod; } int ans=0; for(int i=0; p[i]<maxm; i++) ans=(ans+f[n][king][i])%mod; printf("%d\n",ans); }}
G题
题意是x * y的格子,其中只有一个点是起点,要从这个点出发,每一步只能上下左右的走到相邻格子, 格子可以重复经过,要求所有格子都到达过,且最后回到起点,求所需的最少步数。
找规律题
一行(列)时是特例,如果为1 * y的话,(无论起点在哪)答案为2y-2
当行数或列数有偶数时,发现可以不重复走,答案为x * y
都为奇数时想了半天,最后发现只要重复走一个就行,答案为x * y + 1
I题
此题挺有意思的
三维空间,有一个起点,一个终点,点与点的距离花费就是欧式距离。
但是有一些 worm tube(空间里的线段),可以从这线段上任意一个点进入 worm tube ,然后瞬间从这线段上任意一个点出来,这个过充没有花费。问从起点到终点最小花费多少。
数据规模 0 < T <= 50 , 0 <= N <= 50
首先图论模型比较显然,把起点,终点和worm tube看成图论中的点,做个floyd就求出来了。
关键是…点与点之间的边权(花费)是多少呢?
有两种,一是起点或终点到worm tube的花费就是求点到线段的最小距离啦,这个q神讲过,把线段用参数表示,然后就可以三分了嘛,还有个技巧,为了防止eps太小导致TLE,太大又会因精度不够而WA,用for循环for次数就行了嘛。
第二种是,从一个worm tube到另一个的花费,这个就是求线段到线段的最小距离呀,能不能三分套三分呢,不行!会TLE。这怎么办呢…把点到线段的求法改成用叉积点积求一求就好啦,这样快了很多。
好题!
在WA了八九发之后。。。
不知道为什么把eps改成1e-12后神奇的A了!
#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<cmath>using namespace std;const double eps = 1e-12;int sgn(double x){ if(abs(x)<eps) return 0; if(x>eps) return 1; return -1;}struct Point{ double x, y, z; Point(double _x = 0, double _y = 0, double _z = 0):x(_x), y(_y), z(_z) {} Point operator+(const Point& b)const { return Point(x + b.x, y + b.y, z + b.z); } Point operator-(const Point& b)const { return Point(x - b.x, y - b.y, z - b.z); } Point operator*(const double & k)const { return Point(x * k, y * k, z * k); } Point operator/(const double & k)const { return Point(x / k, y / k, z / k); } Point operator *(const Point &t)const { return Point(y*t.z-z*t.y,-x*t.z+z*t.x,x*t.y-y*t.x); } double operator ^(const Point &t)const { return x*t.x+y*t.y+z*t.z; } double dis(const Point &b)const { return sqrt((x - b.x) * (x - b.x) + (y - b.y) * (y - b.y) + (z - b.z) * (z - b.z)); } double dis2(const Point &b)const { return (x - b.x) * (x - b.x) + (y - b.y) * (y - b.y) + (z - b.z) * (z - b.z); } double len()const { return sqrt(x*x+y*y+z*z); } double len2()const { return x*x+y*y+z*z; } void read() { scanf("%lf%lf%lf", &x, &y, &z); }};typedef Point vect;struct Line{ Point s,e; Line() {} Line(const Point &_s, const Point &_e):s(_s),e(_e) {}} line[55];double d[55][55];double calc(const Point &p,const vect & a,const Point &b){ return a^(b-p);}double P2L(const Point &p,const Line & a){ Point v=a.e-a.s; if(sgn((p-a.s)^(v))<=0)return p.dis(a.s); if(sgn((p-a.e)^(a.s-a.e))<=0) return p.dis(a.e); return sqrt((v*(p-a.s)).len2()/v.len2());}double L2L(const Line &a,const Line &b){ double l=0,r=1; Point v=a.e-a.s; Point s=a.s; while(abs(l-r)>eps) { double x=(l*2+r)/3; double y=(l+r*2)/3; Point px=s+v*x; Point py=s+v*y; if(sgn(P2L(px,b)-P2L(py,b))<0) r=y; else l=x; } return P2L(s+v*l,b);}int main(){ int n, T; Point s, t; scanf("%d", &T); for(int cas = 1; cas <= T; cas ++) { scanf("%d", &n); s.read(); t.read(); for(int i = 0; i < n; i ++) { line[i].s.read(); line[i].e.read(); } for(int i=0; i<=n+1; i++) for(int j=0; j<=n+1; j++) d[i][j]=(i==j)?0:1e99; d[n][n+1]=d[n+1][n]=s.dis(t); for(int i=0; i<n; i++) { d[n][i]=P2L(s,line[i]); d[i][n]=d[n][i]; d[n+1][i]=P2L(t,line[i]); d[i][n+1]=d[n+1][i]; } for(int i=0; i<n; i++) for(int j=i; j<n; j++) if(i!=j) d[i][j]=d[j][i]=L2L(line[i],line[j]); for(int k=0; k<=n+1; k++) for(int i=0; i<=n+1; i++) for(int j=0; j<=n+1; j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); printf("%.8f\n",d[n][n+1]); }}
J题
稍微有点复杂的bfs,细心一点就行。
- BNU Training 2016.07.15 总结
- BNU Training 2016.07.12 总结
- BNU Training 2016.07.18 总结
- BNU Training 2016.07.22 总结
- BNU Training 2016.07.25 总结
- BNU Training 2016.07.29 总结
- BNU Training 2016.07.11
- BNU Training 2015.08.17
- BNU 51640 Training Plan【Dp】
- BNU Training 2016.07.29 Div. 2-B-Levko and Table
- 7.26 team_training (BNU Training 2013.07.26)
- BNU Training 2015 07 27 题解
- BNU新生赛总结
- 【BNU Summer Training 2014.07.25】 Painting Storages (dp)
- 【BNU Summer Training 2014.07.25】 Final Exam Arrangement (贪心)
- BNU Training 2017.07.20 【(2+1+0.233)/11】[待补]
- BNU
- USACO Training第一章总结
- Android梳理不常用widget篇
- mysql中的函数 存储过程和触发器
- 安卓中的延时启动 与 JAVA中的计时器/定时器类
- Codeforces 371C:Hamburgers(二分)
- 类的析构函数
- BNU Training 2016.07.15 总结
- js笔记01
- 架构——Hadoop深入介绍
- python 发送email到qq
- java代理模式和动态代理
- python 发送email到qq
- Counting Sort
- Git系列 --- git-dir & work-tree
- 精彩的一天