集训队的招募马上就要截止了,还是有点不太稳,但要加油
7.30场地址
B题:
题意:给出一个多边形的各个定点,要求所有这些顶点能构成的三角形面积的最小值为多少?
解法:首先三个相邻的点所构成的三角形的面积最小,之后三角型面积的计算方法也是重点
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
ll x[maxn], y[maxn];
int main() {
int n; scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%lld%lld", &x[i], &y[i]);
}
x[n] = x[0]; x[n + 1] = x[1];
y[n] = y[0]; y[n + 1] = y[1];
ll ans = 0x3fffffffffffffff;
for (int i = 0; i < n; i++) {
ll tmp1 = x[i] * y[i + 1] + x[i + 1] * y[i + 2] + x[i + 2] * y[i];
ll tmp2 = x[i] * y[i + 2] + x[i + 1] * y[i] + x[i + 2] * y[i + 1];
//三角形面积的向量计算方法,任意多边形也有类似的性质
if ((tmp1 - tmp2) < ans || i == 0)ans = tmp1 - tmp2;
}
printf("%lld", ans);
return 0;
}
H题:有一个网格图,这个图上面有起点和终点,另外有若干个怪兽点,这些怪兽会将距离小于等于d的人吃掉,求从起点到终点的最短路长度
解法:先从所有的M点开始跑一遍bfs,路径更新的上限是d,算出来所有不能走的点,在vis数组中进行更新,然后再跑一遍起点的bfs,看看能不能跑到终点即可
#include
#include
#include
using namespace std;
int dir[4][2] = { 0,1,0,-1,1,0,-1,0 };
struct node {
int x, y, dis;
};
node st, ed;
int n, m, d, ans = -1;
vector<char>mp[200000 + 5];
vector<int>vis[200000 + 5];
bool check(node nex) {
return nex.x >= 0 && nex.x < n&&nex.y >= 0 && nex.y < m;
}
void bfs1() {
queue q;
for(int i=0;ifor (int j = 0; j < m; j++) {
if (mp[i][j] == 'M') {
q.push(node{ i,j,0 });
vis[i][j] = 1;
}
}
while (!q.empty()) {
node now = q.front(); q.pop();
if (now.dis == d)continue;
node nex;
for (int i = 0; i < 4; i++){
nex.x = now.x + dir[i][0]; // 按照规则生成 下一个状态
nex.y = now.y + dir[i][1];
nex.dis = now.dis + 1; // 计数器加1
if (check(nex)&&!vis[nex.x][nex.y]){
q.push(nex);
vis[nex.x][nex.y] = 1; //访问标记
}
}
}
}
void bfs2() {
queue q;
q.push(node{ st.x,st.y,0 });
if (vis[st.x][st.y] == 1) { ans = -1; return; }
else vis[st.x][st.y] = 1;
while (!q.empty()) {
node now = q.front(); q.pop();
if (now.x == ed.x&&now.y == ed.y) { ans = now.dis; return; }
node nex;
for (int i = 0; i < 4; i++) {
nex.x = now.x + dir[i][0]; // 按照规则生成 下一个状态
nex.y = now.y + dir[i][1];
nex.dis = now.dis + 1; // 计数器加1
if (check(nex) && !vis[nex.x][nex.y]) {
q.push(nex);
vis[nex.x][nex.y] = 1; //访问标记
}
}
}
ans = -1;
}
int main() {
scanf("%d%d%d", &n, &m, &d);
for (int i = 0; i < n; i++) {
vis[i].resize(m + 5); getchar();
for (int j = 0; j < m; j++) {
char c = getchar();
if (c == 'S')st.x = i, st.y = j;
if (c == 'F')ed.x = i, ed.y = j;
mp[i].push_back(c);
}
}
bfs1();
bfs2();
printf("%d\n", ans);
return 0;
}
K题:有n个人,每个人有一个值ai,要求这个人同意的前提是他前面有ai个人已经同意了,当然你可以强制让这个人同意,给出一个要求的同意人数m,问最少需要说服多少个人
解法:二分答案,你要记住二分的关键是先假设一个答案,然后看在这个答案的基础上算出来的其他变量的情况(比如说这道题里面就是加入答案是mid的话你最多可以睡服的人数),然后在根据这个来进行判断二分的方向
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=200005;
int n,m,a[maxn];
bool check(int k)
{
int ans=0;//ans为已经同意的人(包含说服的)
for(int i=1;i<=n;i++)
{
if(a[i]<=ans)ans++;//第i个人前面同意的人数已经超过了a[i],所以她也会同意
else if(k)ans++,k--;//否则就贪心的说服他,因为早说服肯定比晚说服好
}
return ans>=m;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int l=0,r=m,mid,ans=m;
//二分答案
while(l<=r)
{
mid=(l+r)/2;
if(check(mid))r=mid-1,ans=mid;
else l=mid+1;
}
printf("%d\n",ans);
return 0;
}