2012省赛
来源:互联网 发布:linux新建文档命令 编辑:程序博客网 时间:2024/04/25 03:36
B题, 简单搜索
int dx[] = { -1,1, 2, 2, -1,1 ,-2,-2 };int dy[] = { 2,2 , -1 , 1 ,-2 , -2 , 1 , -1};int bx[] = { 0,1 ,0,-1 };int by[] = { 1,0,-1,0};int ans, n, m, k, ld;int map[10][10];bool can(int x, int y){ return x>=0 && x<n && y>=0 && y<m;}void dfs(int x, int y, int d){ if(!can(x, y)) return ; if(map[x][y])return; if(ld==d) { ans++; return; } map[x][y]=1; for (int i=0; i<4; ++i) { int bbx=x+bx[i]; int bby=y+by[i]; if(!can(bbx, bby))continue; if(map[bbx][bby]==2) continue; int nx=x+dx[i<<1]; int ny=y+dy[i<<1]; dfs(nx, ny, d+1); nx=x+dx[i<<1|1]; ny=y+dy[i<<1|1]; dfs(nx, ny, d+1); } map[x][y]=0;}int main (){ while (~scanf("%d%d%d", &n, &m, &k)) { if(k==-1) break; memset (map, 0, sizeof(map)); ans=0; for (int i=0; i<k; ++i) { int a, b; scanf("%d%d", &a, &b); a--, b--; map[a][b]=2; } ld=m*n-k; dfs(0, 0, 1); printf("%d\n", ans); } return 0;}
C题, 枚举每对在同一直线上的2点, 在找纵坐标在2点间的x的最大值, 用区间最值RMQ, st算法O(1)找出, 区间要先对纵坐标离散化
using namespace std;const int maxn=2000+123;struct Node{ int x, y, id;}node[maxn];bool cmp1(Node a, Node b){ return a.y<b.y;}bool cmp2(Node a, Node b){ if(a.x==b.x)return a.y<b.y; return a.x<b.x;}///int a[maxn], dp[maxn][50];int bit(int x)// bit-op for getting first non-zero bit{ if(x==0)return 0; int n=31; if((x>>16)==0){n-=16; x<<=16;} if((x>>24)==0){n-=8; x<<=8;} if((x>>28)==0){n-=4; x<<=4;} if((x>>30)==0){n-=2; x<<=2;} return n-(x>>31);}void ST(int x)// for st-table{ for (int i=0; i<x; ++i) dp[i][0]=a[i]; int lgx=bit(x); //printf("%d %d %d\n", x, lgx, lgx1); for (int i=1; i<=lgx; ++i) { for(int j=x-1; j>=0; --j) { dp[j][i]=dp[j][i-1]; if(j+(1<<(i-1))<=x)dp[j][i]=max(dp[j][i], dp[j+(1<<(i-1))][i-1]); } }}int RMQ(int s, int t){ int lgx=bit(t-s+1)-1; //printf("%d %d %d\n", lgx, lgx1, t-s+1); return max(dp[s][lgx], dp[t-(1<<lgx)+1][lgx]);}int main (){ int cas; scanf("%d", &cas); for (int I=1; I<=cas; ++I) { int n; scanf("%d", &n); for (int i=0; i<n; ++i) { scanf("%d%d", &node[i].x, &node[i].y); node[i].id=0; } sort(node, node+n, cmp1); node[0].id=0; int cnt=0; memset (a, 0, sizeof(a)); for (int i=1; i<n; ++i) { if(node[i].y!=node[i-1].y) node[i].id=++cnt; else node[i].id=cnt; } for (int i=0; i<n; ++i) { a[node[i].id]=max(a[node[i].id], node[i].x); //printf("a[%d]= %d\n", node[i].id, a[node[i].id]); } ST(cnt+1); sort(node, node+n, cmp2); int ans=-1, t; for (int i=0, seg=0; i<n; ++i) { for (int j=i+1; j<n; ++j) { if(node[i].x!=node[j].x) break; if(node[i].id+1<=node[j].id-1) { t=RMQ(node[i].id+1, node[j].id-1); if(t-node[i].x>node[j].y-node[i].y) ans=max(ans, node[j].y-node[i].y+t-node[i].x); //printf("%d %d %d %d\n", node[i].id+1, node[j].id-1, t, a[node[i].id+1]); } } } printf("Case %d: %d\n", I, ans); } return 0;}
E题, DP 三维状态, 按行分阶段, dp[i][j][k]表示走到第i行2人位置分别为j,k的最小值
const int MAXN = 1001;int dp [MAXN][12][12];const int inf = 0x7fffffff;char lc[MAXN][20];int abs ( int x ){ return x < 0 ? -x : x ;}int main(){ int n , m , mi , ma , x , y; int Case; scanf("%d",&Case ); for ( int k = 1 ; k <= Case ;k ++ ) { scanf("%d%d%d%d%d%d",&n,&m,&mi,&ma,&x,&y); getchar(); for ( int i =0 ; i < n ; i ++ ) for ( int l = 0 ; l < m ; l ++ ) for ( int c = 0 ; c < m; c ++ ) dp[i][l][c] = inf; dp[0][x][y] = 0; for ( int i = 0 ; i < n ; i ++) scanf("%s",lc[i]); for ( int i = 1 ; i < n ; i ++ ) for ( int l = 0 ; l < m ; l ++ ) for ( int c = l+mi ; c <= l+ma && c < m ; c ++ ) { if ( lc[i][l] == '.' || lc[i][c] == '.' ) continue; for ( int l1 = 0 ; l1 < m; l1 ++ ) for ( int c1 = l1+mi ; c1 <= l1+ma && c1 < m; c1 ++ ) { if ( dp[i-1][l1][c1] == inf ) continue; if ( dp[i][l][c] > dp[i-1][l1][c1] + abs(l-l1) + abs(c-c1) ) dp[i][l][c] = dp[i-1][l1][c1] + abs(l-l1) + abs(c-c1); } int ans = inf; for ( int i = 0 ; i < m ;i ++ ) for ( int j = 0 ; j < m; j ++ ) if ( ans > dp[n-1][i][j] ) ans = dp[n-1][i][j]; if ( ans == inf ) ans = -1; printf("%d\n" ,ans ); } return 0;}
F题 , 计算几何, 用到一些简单的数学几何知识和三角函数公式,先求出原点到圆心所在直线的斜率, 然后利用tan公式求出上下切线的斜率, 再求出映射到x=d的区间, 之后扫一遍 求出阴影的长度并。
struct segment{ double y1, y2;}seg[150];double calc_k1( double a, double b, double r ){ double tan1, tan2; tan1 = r / ( sqrt( a * a + b * b - r * r ) ); tan2 = b / a; return ( tan1 + tan2 ) / ( 1 - tan1 * tan2 );}double calc_k2( double a, double b, double r ){ double tan1, tan2; tan1 = r / ( sqrt( a * a + b * b - r * r ) ); tan2 = b / a; return ( tan2 - tan1 ) / ( 1 + tan1 * tan2 );}double calc_pt1( double k1, double y ){ return k1 * y;}double calc_pt2( double k2, double y ){ return k2 * y;}bool cmp(segment a, segment b){ if(a.y1==b.y1)return a.y2>b.y2; return a.y1>b.y1;}int main(){ double d; int n; double x, y, r; while( cin >> d >> n, n ) { for( int i = 0; i < n; i++ ) { cin >> x >> y >> r; double k1 = calc_k1( x, y, r ); double pt1 = calc_pt1( k1, d ); double k2 = calc_k2( x, y, r ); double pt2 = calc_pt2( k2, d ); seg[i].y1 = pt1; seg[i].y2 = pt2; } sort( seg, seg + n, cmp ); double ans = 0.0; ans = seg[0].y1 - seg[0].y2; double lowest = seg[0].y2; for (int i=1 ; i<n; ++i) { if( seg[i].y1 <= lowest ) { ans += ( seg[i].y1 - seg[i].y2 ); lowest = seg[i].y2; } else if( seg[i].y1 > lowest ) { if( seg[i].y2 < lowest ) { ans += ( -seg[i].y2 + lowest ); lowest = seg[i].y2; } if( seg[i].y2 > lowest ) ans += 0; } } printf( "%.2lf\n", ans ); } return 0;}
G题 , 树的性质, yy结论题, 因为之需要修复一个RPedge, 那么其减少的RPpath条数必然是该edge两边的2个非RPedge构成的分量的乘积, 先处理所有的非RPedge,用带权值的并查集维护连通分量和分量中点的个数。
typedef long long ll;const int maxn=200000+123;int rank[maxn], p[maxn];int find(int x){ if(x!=p[x])p[x]=find(p[x]); return p[x];}void merge(int a, int b){ int fa=find(a), fb=find(b); if(fa==fb)return ; if(rank[fa]>rank[fb])p[fb]=fa, rank[fa]+=rank[fb]; else p[fa]=fb, rank[fb]+=rank[fa]; //if(rank[fa]==rank[fb])rank[fb]++;}struct Node{ int u, v;}edge[maxn];void init(int x){ for (int i=1; i<=x; ++i) { p[i]=i; rank[i]=1; }}int main(){ int n; while (~scanf("%d", &n)) { init(n); int cnt=0; for (int i=1; i<n; ++i) { int a, b, c; scanf("%d%d%d", &a, &b, &c); if(c==1) { //printf("%d %d %d cnt===%d\n", a, b, c, cnt); edge[cnt].u=a; edge[cnt].v=b; cnt++; } else merge(a, b); } ll ans=(ll)n*(ll)(n-1)/2; for (int i=1; i<=n; ++i) { if(i==find(i)) ans-=(ll)rank[i]*(ll)(rank[i]-1)/2; } //printf("%lld cnt==%d\n", ans, cnt);// for (int i=1; i<=n; ++i)// {// printf("%d %d %d\n", i, rank[i], p[i]);// } ll tmp, maxt=0; for (int i=0; i<cnt; ++i) { const int &a=edge[i].u; const int &b=edge[i].v; int fa=find(a), fb=find(b); const ll ra=rank[fa]; const ll rb=rank[fb]; ll rc=ra+rb; tmp=rc*(rc-1)/2-ra*(ra-1)/2-rb*(rb-1)/2; //printf("tmp==%d\n", tmp); maxt=max(tmp, maxt); } printf("%lld\n", ans-maxt); } return 0;}
J题 , 组合数学, 非降路径公式, 用DP也可以解
- 2012省赛
- 2012省赛,数学题
- 2012年 蓝桥杯C++省赛 古堡算式
- 蓝桥杯 2012省赛 (1--10题)
- 省赛
- 省赛
- 省赛
- 省赛
- 省赛。。。
- 省赛
- 2012年第三届蓝桥杯C/C++省赛 微生物增殖
- 黑龙江省2012年ACM-ICPC省赛J题The least average cost【最小均值回路】
- [2012山东ACM省赛] n a^o7 !(模拟,字符替换)
- [2012山东ACM省赛] The Best Seat in ACM Contest (模拟)
- [2012山东ACM省赛] Fruit Ninja II (三重积分,椭球体积)
- [2012山东ACM省赛] Pick apples (贪心,完全背包,枚举)
- 省赛 总结
- 省赛1
- 关于《学习基于ARM平台的嵌入式系统》的收获和思考
- IO端口与IO内存
- 免锁算法----原子变量
- 原子操作
- 应用程序和内核模块的区别
- 2012省赛
- linux_ioctl与内核交换数据
- 将大数据的数据库导入phpmyadmin的方法1
- poll机制分析(韦东山)
- hduoj 3415 Max Sum of Max-K-sub-sequence
- Binary XML file line #11: You must supply a layout_width attribute
- 流行的视觉跟踪方法
- 简明 Vim 练级攻略
- 如果你对生活毫无兴趣了 看看这个吧