只想到一种情况 另外一种情况是参考别人的
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]; else sum += a[1] + a[2] + a[3]; printf("%I64d\n",sum); } return 0; }
这题是看书学习的 据说是经典题 黑书上有讲 转换成点是否在三角形内 三维的叉积 点积
好题
#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; else return 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"); else puts("NO"); } return 0; }
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; else dis[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; }
找出循环节就行了 自己就是速度太慢了 简单题也写了半天
#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; }
我直接用了优先队列 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(); } else q.push(x); } } return 0; }
一看是二分 开始错了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; else r = 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; }
一看题意 发现是割点 书上看到过 学了下 一下就懂了 裸的应用 可以看一下白皮书
一个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; }
记忆化搜索 就滑雪那样的 没有了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; }
不会啊 求告知
二维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; }