2014台州学院ACM集训队寒假练习赛1

来源:互联网 发布:软件项目主要技术指标 编辑:程序博客网 时间:2024/05/04 06:20

A Bridge

只想到一种情况 另外一种情况是参考别人的

2个人为一轮

a b c d

a b 去 a 回 c d 去 b 回(最小的2个去 2个在回来 。。。)

其实还有一种

a b 去 a 回 a c 去 a 回(只是最小的来回)

2中情况要具体分析 不能全是第一种 全是第二种 每2个2个人取小值

这个真不会

语言: C++   用户:614173971  提交时间 : 2014-01-15 16:33:33.0#include <cstdio>#include <algorithm>using namespace std;const __int64 MAX = 100010;__int64 a[MAX];int main(){__int64 n;__int64 i;while(~scanf("%I64d",&n)){for(i = 1;i <= n; i++)scanf("%I64d",&a[i]);if(n == 0){printf("%0\n");continue;}if(n == 1){printf("%I64d\n",a[1]);continue;}sort(a+1,a+n+1);__int64 sum = 0;for(i = n; i >= 4; i -= 2)sum += min(2 * a[1] + a[i] + a[i-1],a[1] + 2 * a[2] + a[i]);if(n%2 == 0)sum += a[2];elsesum += a[1] + a[2] + a[3];printf("%I64d\n",sum);}return 0;} 

 

B 3-sided dice

这题是看书学习的 据说是经典题 黑书上有讲 转换成点是否在三角形内 三维的叉积 点积

好题

#include <cstring>#include <cmath>#include <cstdio>const double eps = 1e-10;struct Point3{double x, y, z;Point3(double x=0, double y=0, double z=0):x(x),y(y),z(z){}};typedef Point3 Vector3;Vector3 operator + (Vector3 A, Vector3 B){return Vector3(A.x+B.x, A.y+B.y, A.z+B.z);}Vector3 operator - (Vector3 A, Vector3 B){return Vector3(A.x-B.x, A.y-B.y, A.z-B.z);}int dcmp(double x){if(fabs(x) < eps)return 0;elsereturn x < 0 ? -1 : 1;}double Dot(Vector3 A, Vector3 B)//点积 {return A.x*B.x + A.y*B.y + A.z*B.z;}double Length(Vector3 A)//向量长度 {return sqrt(Dot(A, A));}Vector3 Cross(Vector3 A, Vector3 B)//求叉积 {return Vector3(A.y*B.z - A.z*B.y, A.z*B.x - A.x*B.z, A.x*B.y - A.y*B.x);}double Area(Point3 p0, Point3 p1, Point3 p2){return Length(Cross(p1-p0, p2-p0));}bool PointInTri(Point3 p, Point3 p0, Point3 p1, Point3 p2)//判断p是否在三角形内 {double area1 = Area(p, p0, p1);double area2 = Area(p, p1, p2);double area3 = Area(p, p2, p0);if(Area(p0,p1,p2) == 0)//3个点没有成为三角形 线段或者点的情况 {if(Dot(p0-p, p1-p) < 0)return true;if(Dot(p1-p, p2-p) < 0)return true;if(Dot(p2-p, p0-p) < 0)return true;return false;}if(dcmp(area1) == 0)//不能在三角形边上 return false;if(dcmp(area2) == 0)return false;if(dcmp(area3) == 0)return false;return dcmp(area1 + area2 + area3 - Area(p0,p1,p2)) == 0;}bool ok(Point3 p, Point3 p0, Point3 p1, Point3 p2)//判断p是否在三角形所在的平面上 {Vector3 A = Cross(p1-p0, p2-p0);Vector3 B = p-p0;return dcmp(Dot(A, B)) == 0; }int main(){double x,y,z;while(scanf("%lf %lf %lf",&x,&y,&z),x||y||z){Point3 p0(x,y,z);scanf("%lf %lf %lf",&x,&y,&z);Point3 p1(x,y,z);scanf("%lf %lf %lf",&x,&y,&z);Point3 p2(x,y,z);scanf("%lf %lf %lf",&x,&y,&z);Point3 p(x,y,z);if(ok(p,p0,p1,p2) && PointInTri(p,p0,p1,p2))puts("YES");elseputs("NO");}return 0;}


 

C Relocation

dijkstra 因为k最多就5个 求出k个超市到所有点的距离 然后枚举起点(除去k个点)途径k个超市 在回来 你们所以需要的条件已经通过dijkstra求出来了

只需枚举求最小值 n*2^k 加上最短路 k*nlogn

#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <algorithm>#define pii pair<int,int> #define INF 999999999;using namespace std;const int MAX = 10010;vector <pii> edge[MAX];int ok[MAX];int dis[10][MAX];int ans[10];int n,m,k;void dijkstra(int s, int pos){priority_queue <pii, vector<pii> ,greater<pii> > q;bool vis[MAX];for(int i = 1;i <= n; i++){if(i == s)dis[pos][i] = 0;elsedis[pos][i] = INF;}memset(vis,false,sizeof(vis));q.push(make_pair(0,s));while(!q.empty()){pii u = q.top();q.pop();int x = u.second;if(vis[x])continue;vis[x] = true;int len = edge[x].size();for(int i = 0; i < len; i++){pii v = edge[x][i];if(dis[pos][v.second] > dis[pos][x] + v.first){dis[pos][v.second] = dis[pos][x] + v.first;q.push(make_pair(dis[pos][v.second],v.second));}}}}int main(){int i,j;int u,v,w;int sum = INF;scanf("%d %d %d",&n,&m,&k);for(i = 1;i <= k; i++){scanf("%d",&j);ans[i] = j;ok[j] = i;}for(i = 1;i <= m; i++){scanf("%d %d %d",&u,&v,&w);edge[u].push_back(make_pair(w,v));edge[v].push_back(make_pair(w,u));}for(i = 1; i <= k; i++)dijkstra(ans[i],i);for(i = 1;i <= n; i++){if(ok[i])continue;sort(ans+1,ans+1+k);do{int cnt = 0;for(j = 1;j <= k; j++){if(j == 1)cnt += dis[ok[ans[j]]][i];else if(j == k)cnt += dis[ok[ans[j]]][i] + dis[ok[ans[j]]][ans[j-1]];else cnt += dis[ok[ans[j]]][ans[j-1]];}if(sum > cnt)sum = cnt;//printf("%d\n",cnt);}while(next_permutation(ans+1,ans+k+1));}printf("%d\n",sum);return 0;}


 

D Treasure Hunt

找出循环节就行了 自己就是速度太慢了 简单题也写了半天

#include <cstdio>#include <cstring>#include <cstdio>using namespace std;struct node{int u;int v;}a[220][22];int b[100000];int mp[220][22];int main(){int n,m,t,s;int i,j,u,v;int cnt;while(scanf("%d %d %d %d",&m,&t,&s,&n)!=EOF){cnt = 1;memset(mp,0,sizeof(mp));for(i = 1;i <= m; i++){for(j = 1;j <= t; j++){scanf("%d %d",&u,&v);a[i][j].u = v;a[i][j].v = u;}}u = s;v = 1;mp[s][1] = cnt;b[cnt++] = s;while(1){int uu = u;int vv = v;u = a[uu][vv].u;v = a[uu][vv].v;//printf("  %d %d\n",u,v);if(cnt-1 == n){printf("%d\n",b[cnt-1]);break;}if(mp[u][v]){int k = cnt - mp[u][v];int nn = (n - mp[u][v] + 1) % k;if(nn == 0)nn = k;printf("%d\n",b[mp[u][v] - 1 + nn]);//printf("%d\n",k);break;}else{mp[u][v] = cnt;b[cnt++] = u;}}}return 0;}


 

E The End of Corruption

我直接用了优先队列 1A 是不是数据水了啊 5s 用了340ms

#include <cstdio>#include <cstring>#include <queue>using namespace std;int main(){int n,m;int i,x;while(scanf("%d %d",&n,&m)!=EOF){priority_queue <int> q;for(i = 1;i <= n + m; i++){scanf("%d",&x);if(x == -1){printf("%d\n",q.top());q.pop();}elseq.push(x);}}return 0;}

F What is the Rank?

一看是二分 开始错了2次 犯傻了 

每次二分到那个位置把那个数插进去 数组很难能实现 10秒我就乱搞了 用vector insert 结果对了

#include <cstdio>#include <cstring>#include <vector>using namespace std;const int MAX = 45010;int a[MAX];vector <int> dp;int pos[MAX];int main(){int n;int i,j,l,r,m,len;scanf("%d",&n);for(i = 0;i < n; i++)scanf("%d",&a[i]);dp.push_back(a[0]);pos[0] = 0;len = 0;for(i = 1;i < n; i++){l = 0;r = dp.size() - 1;while(l <= r){m = (l + r) >> 1;if(a[i] < dp[m])l = m + 1;elser = m - 1;}dp.insert(dp.begin()+l,a[i]);pos[i] = l;}for(i = 0;i < n; i++)printf("%d\n",pos[i]+1);return 0;}


 

G Critical Intersections

一看题意 发现是割点 书上看到过 学了下 一下就懂了 裸的应用 可以看一下白皮书

一个dfs算法解决

#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;const int MAX = 310;vector <int> G[MAX];int pre[MAX];int low[MAX];bool iscnt[MAX];int n,m;int cnt = 0;//时间戳 int dfs(int u,int fa){int lowu = pre[u] = ++cnt;int child = 0;//子节点数for(int i = 0; i < G[u].size(); i++){int v = G[u][i];if(!pre[v]){child++;int lowv = dfs(v,u);lowu = min(lowu,lowv);if(lowv >= pre[u]) iscnt[u] = true;}else if(pre[v] < pre[u] && v != fa){lowu = min(lowu,pre[v]);}}if(fa < 0 && child == 1)iscnt[u] = false;low[u] = lowu;return lowu;}int main(){int i,u,v;scanf("%d %d",&n,&m);for(i = 1;i <= m; i++){scanf("%d %d",&u,&v);G[u].push_back(v);G[v].push_back(u);}dfs(1,-1);int sum = 0;for(i = 1;i <= n; i++)if(iscnt[i])sum++;printf("%d\n",sum);return 0;}

 

H Word Hopping

记忆化搜索 就滑雪那样的 没有了4个方向 更简单了

题意看清就行

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;char a[120][20];int dp[120];int vis[120];int n;bool ok1(char *s1,char *s2){int i,j;int cnt = 0;int len = strlen(s1);for(i = 0;i < len; i++){if(s1[i] > s2[i])return false;if(s1[i] < s2[i]){for(j = i + 1;j < len; j++)if(s2[i] == s1[j])break;if(j == len)return false;}if(s1[i] != s2[i])cnt++;}if(cnt != 1)return false;return true;}bool ok2(char *s1,char *s2){int i,j;int cnt = 0;int len = strlen(s2);for(i = 0;i < len; i++){if(s1[i] != s2[i])break;}if(i == len)return true;for(j = i,i = j + 1; j < len; i++,j++)if(s1[i] != s2[j])return false;return true;}bool check(char *s1,char *s2){if(strlen(s1) < strlen(s2))return false;else if(strlen(s1) == strlen(s2)){if(ok1(s1,s2))return true;}else if(strlen(s1) - 1 == strlen(s2)){if(ok2(s1,s2))return true;}return false;}int dfs(int u){if(vis[u])return dp[u];int i;int max = 0;for(i = 1;i <= n; i++){if(u == i)continue;if(!check(a[u],a[i]))continue;int temp = dfs(i);if(max < temp)max = temp;}dp[u] = max + 1;vis[u] = true;return dp[u];}int main(){int i,j;while(scanf("%d",&n)!=EOF){for(i = 1;i <= n; i++)scanf("%s",a[i]);memset(dp,0,sizeof(dp));memset(vis,false,sizeof(vis));int max = 0;for(i = 1;i <= n; i++){int temp = dfs(i);if(max < temp)max = temp;}printf("%d\n",max);}return 0;}

I Siruseri Metro System

 不会啊 求告知

 

J Equal Gifts

二维01背包 一不小心A了 一维也可以的

#include <cstdio>#include <algorithm>using namespace std;struct node{int u;int v;}a[200];bool dp[2][100000];bool map[2][100000];int main(){int n,i,j,k;int m = 0;int sum = 0;while(scanf("%d",&n)!=EOF){memset(dp,false,sizeof(dp));memset(map,false,sizeof(map));sum = 0;for(i = 1;i <= n; i++){scanf("%d %d",&a[i].u,&a[i].v);sum += a[i].u + a[i].v;}map[1][0] = map[0][0] = true;for(i = 1;i <= n; i++){memcpy(dp,map,sizeof(map));memset(map,false,sizeof(map));for(j = m; j >= 0;j--){if(dp[0][j]){map[0][j+a[i].u] = true;map[0][j+a[i].v] = true;m = max(m,j+a[i].u);m = max(m,j+a[i].v);}if(dp[1][j]){map[1][j+a[i].u] = true;map[1][j+a[i].v] = true;m = max(m,j+a[i].u);m = max(m,j+a[i].v);}}}for(i = sum/2 ;i >= 1; i--){if(map[0][i] || map[1][i])break;}printf("%d\n",sum-2*i);}return 0;}


 

 

0 0