7.30总结当日


集训队的招募马上就要截止了,还是有点不太稳,但要加油


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() {
    queueq;
    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() {
    queueq;
    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;
}

你可能感兴趣的:(2018暑假ACM集训)