7.30总结当日
集训队的招募马上就要截止了,还是有点不太稳,但要加油
7.30场地址
B题:
题意:给出一个多边形的各个定点,要求所有这些顶点能构成的三角形面积的最小值为多少?
解法:首先三个相邻的点所构成的三角形的面积最小,之后三角型面积的计算方法也是重点
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 using namespace std; 5 typedef long long ll; 6 const int maxn = 2e5 + 5; 7 ll x[maxn], y[maxn]; 8 9 int main() { 10 int n; scanf("%d", &n); 11 for (int i = 0; i < n; i++) { 12 scanf("%lld%lld", &x[i], &y[i]); 13 } 14 x[n] = x[0]; x[n + 1] = x[1]; 15 y[n] = y[0]; y[n + 1] = y[1]; 16 ll ans = 0x3fffffffffffffff; 17 for (int i = 0; i < n; i++) { 18 ll tmp1 = x[i] * y[i + 1] + x[i + 1] * y[i + 2] + x[i + 2] * y[i]; 19 ll tmp2 = x[i] * y[i + 2] + x[i + 1] * y[i] + x[i + 2] * y[i + 1]; 20 //三角形面积的向量计算方法,任意多边形也有类似的性质 21 if ((tmp1 - tmp2) < ans || i == 0)ans = tmp1 - tmp2; 22 } 23 printf("%lld", ans); 24 return 0; 25 }
H题:有一个网格图,这个图上面有起点和终点,另外有若干个怪兽点,这些怪兽会将距离小于等于d的人吃掉,求从起点到终点的最短路长度
解法:先从所有的M点开始跑一遍bfs,路径更新的上限是d,算出来所有不能走的点,在vis数组中进行更新,然后再跑一遍起点的bfs,看看能不能跑到终点即可
1 #include<cstdio> 2 #include<queue> 3 #include<vector> 4 using namespace std; 5 int dir[4][2] = { 0,1,0,-1,1,0,-1,0 }; 6 struct node { 7 int x, y, dis; 8 }; 9 node st, ed; 10 int n, m, d, ans = -1; 11 vector<char>mp[200000 + 5]; 12 vector<int>vis[200000 + 5]; 13 14 bool check(node nex) { 15 return nex.x >= 0 && nex.x < n&&nex.y >= 0 && nex.y < m; 16 } 17 18 void bfs1() { 19 queue<node>q; 20 for(int i=0;i<n;i++) 21 for (int j = 0; j < m; j++) { 22 if (mp[i][j] == 'M') { 23 q.push(node{ i,j,0 }); 24 vis[i][j] = 1; 25 } 26 } 27 while (!q.empty()) { 28 node now = q.front(); q.pop(); 29 if (now.dis == d)continue; 30 node nex; 31 for (int i = 0; i < 4; i++){ 32 nex.x = now.x + dir[i][0]; // 按照规则生成 下一个状态 33 nex.y = now.y + dir[i][1]; 34 nex.dis = now.dis + 1; // 计数器加1 35 if (check(nex)&&!vis[nex.x][nex.y]){ 36 q.push(nex); 37 vis[nex.x][nex.y] = 1; //访问标记 38 } 39 } 40 } 41 } 42 43 void bfs2() { 44 queue<node>q; 45 q.push(node{ st.x,st.y,0 }); 46 if (vis[st.x][st.y] == 1) { ans = -1; return; } 47 else vis[st.x][st.y] = 1; 48 while (!q.empty()) { 49 node now = q.front(); q.pop(); 50 if (now.x == ed.x&&now.y == ed.y) { ans = now.dis; return; } 51 node nex; 52 for (int i = 0; i < 4; i++) { 53 nex.x = now.x + dir[i][0]; // 按照规则生成 下一个状态 54 nex.y = now.y + dir[i][1]; 55 nex.dis = now.dis + 1; // 计数器加1 56 if (check(nex) && !vis[nex.x][nex.y]) { 57 q.push(nex); 58 vis[nex.x][nex.y] = 1; //访问标记 59 } 60 } 61 } 62 ans = -1; 63 } 64 65 int main() { 66 scanf("%d%d%d", &n, &m, &d); 67 for (int i = 0; i < n; i++) { 68 vis[i].resize(m + 5); getchar(); 69 for (int j = 0; j < m; j++) { 70 char c = getchar(); 71 if (c == 'S')st.x = i, st.y = j; 72 if (c == 'F')ed.x = i, ed.y = j; 73 mp[i].push_back(c); 74 } 75 } 76 bfs1(); 77 bfs2(); 78 printf("%d\n", ans); 79 return 0; 80 }
K题:有n个人,每个人有一个值ai,要求这个人同意的前提是他前面有ai个人已经同意了,当然你可以强制让这个人同意,给出一个要求的同意人数m,问最少需要说服多少个人
解法:二分答案,你要记住二分的关键是先假设一个答案,然后看在这个答案的基础上算出来的其他变量的情况(比如说这道题里面就是加入答案是mid的话你最多可以睡服的人数),然后在根据这个来进行判断二分的方向
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<vector> 7 #include<queue> 8 #include<map> 9 #include<set> 10 #include<ctime> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int>P; 14 const int INF=0x3f3f3f3f,maxn=200005; 15 int n,m,a[maxn]; 16 bool check(int k) 17 { 18 int ans=0;//ans为已经同意的人(包含说服的) 19 for(int i=1;i<=n;i++) 20 { 21 if(a[i]<=ans)ans++;//第i个人前面同意的人数已经超过了a[i],所以她也会同意 22 else if(k)ans++,k--;//否则就贪心的说服他,因为早说服肯定比晚说服好 23 } 24 return ans>=m; 25 } 26 27 int main() 28 { 29 scanf("%d%d",&n,&m); 30 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 31 int l=0,r=m,mid,ans=m; 32 //二分答案 33 while(l<=r) 34 { 35 mid=(l+r)/2; 36 if(check(mid))r=mid-1,ans=mid; 37 else l=mid+1; 38 } 39 printf("%d\n",ans); 40 return 0; 41 }