当前位置: 首页 > 工具软件 > Grakn.AI > 使用案例 >

Grakn Forces 2020 A - D

梁丘弘
2023-12-01

1408A - Circle Coloring

题意

给定长度n为三个数组a,b,c其中ai != bi != ci 从中选择一个收尾相连的数组是数组的第i为元素是ai ,bi 或ci 的一个,但相邻的元素不能相同

思路

很简单的一道模拟题,可以从下标为1开始找只要保证这个数和他前面的一个数不相等就可以,最后一个数特判一下,因为ai != bi != ci 所以每个数是必然满足条件的

代码

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 1e3+10;
int a[N],b[N],c[N];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        for(int i = 0;i < n;i++) scanf("%d",&a[i]);
        for(int i = 0;i < n;i++) scanf("%d",&b[i]);
        for(int i = 0;i < n;i++) scanf("%d",&c[i]);
        int last = a[0];
        vector<int >ans;
        ans.push_back(last);
        for(int i = 1;i<n - 1;i++){
            if(a[i] != last) last = a[i];
            else if(b[i] != last) last = b[i];
            else if(c[i] != last) last = c[i];
            ans.push_back(last);
        }
        if(a[n - 1] != last && a[n - 1] != ans[0]) last = a[n - 1];
        else if(b[n - 1] != last && b[n - 1] != ans[0]) last = b[n - 1];
        else last = c[n - 1];
        ans.push_back(last);
        for(auto x : ans){
            cout<<x<<' ';
        }
        puts("");
    }
    
    return 0;
}

1408B - Arrays Sum

题意

给定一个非严格单调递增的数组a,求数组a可以由最少多少个数组b组成,其中数组b也是非严格单调递增的,但是数组b的元素个数有限,只能为k个

思路

首先先想特殊的
····当所有元素都相同的话只有一个
····当次数为1的话,如果含有不同的元素那么必然不可能
对于剩下的情况
····由于b也是单调递增的,因为最少,我能就尽可能希望每次能够多表示一些ai,不难想到每次除了第一次以外只能表示出k - 1一个a中的元素,所以就等价为 an - an-1 ,…… a3 - a2,a2 - a1 中不为0的所有数即为c,每次选择k - 1个至少需要多少次 ⌈ c k − 1 ⌉ \lceil \frac{c}{k-1} \rceil k1c,(因为第一次可以是k次,所以可以忽略a1使第一次为k - 1次)

代码

#include<iostream>
 
using namespace std;
const int N = 110;
int a[N];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i = 1;i<=n;i++) scanf("%d",&a[i]);
        if(a[1] == a[n]) {
            puts("1");
            continue;
        }
        else if(k == 1){
            puts("-1");
            continue;
        }
        int c = 0;
        for(int i = n;i > 1;i--){
            int x = a[i] - a[i - 1];
            if(x > 0) c++;
        }
        cout<<(c + k - 2)/(k - 1) <<endl;
    }
    
    return 0;
}

1408C - Discrete Acceleration

题意

给定长度为L的一条路,一个人从0出发,一个从L出发,他们相向而行,给定一个数组a(递增)每一次通过a中的一个节点,他的速度就会加1(默认速度为1),求多少秒后,他们会相遇

思路

可以使用双指针的思路,求两个人谁先到达离自己最近的点,然后这个人的速+1,另个一人也走这个时间段的路程,然后继续这个过程,直到所有的点都被用过,最后他们以各自的速度走完剩下的路程

代码

#include<iostream>
 
using namespace std;
const int N = 1e5+10;
int a[N];
 
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n,l;
        scanf("%d%d",&n,&l);
        for(int i = 1;i<=n;i++) scanf("%d",&a[i]);
        int i = 1,j = n;  // 离他们最近的点
        double s = 0,e = l; //  初始位置
        int v1 = 1,v2 = 1; // 初始速度
        double ans = 0;   // 统计答案
 
        while(i <= j){  // 遍历所有的点
            double t1 = (double)(a[i] - s)/v1;  // 向右走,走到下一个点的 时间
            double t2 = (double)(e - a[j])/v2;  // 向左走,走到下一个点的 时间
            // cout<<t1<<' '<<t2<<endl;
            // 判断谁先走到下一个点,给答案加上这个点对应的时间
            // 走到这个点的速度+1,另一个人走这段时间相应的路程
            if(t1 < t2){  
                ans += t1;  
                s = a[i];
                e = e - v2 * t1;
                v1++;
                i++;
            }
            else{
                ans += t2;
                e = a[j];
                s = v1 * t2 + s;
                v2++;
                j--;
            }
        }
        // cout<<v1<<' '<<v2<<endl;
        // cout<<e<<' '<<s<<endl;
        ans += (e - s ) / (v1 + v2);  // 剩下的路程一起走的时间
        printf("%.8lf\n",ans);
    }
    
    return 0;
}

1408D - Searchlights

题意

给定n个机器人的坐标(ai,bi)和m个灯光的照射范围(ci,di)(每个灯光可以照射给定点的以下区域),你可以控制所有的机器人,x方向走一个或y方向走一个,询问所有机器人都逃离灯光的照射所需要的最少步数

思路

对于每个机器人走的步数,可以假设为(ai + x, bi + y) ,对于每个照射区域,都要满足 ai + x <= cj ,bi + y <= dj不成立,当 ai + x <= cj ,要满足 y >= dj - bi + 1,所以我们可以用一个数组f表示这种情况,该数组的下标i表示移动的步数小于等于i的情况下需要移动的步数,但是该步数并不是最直接的意思,他还需要依赖大于i的最大步数,比如:
····当 ai <= cj且bi <= dj,我们只需记录f[cj - ai](cj - ai表示最大情况下的x满足ai + x <= cj )需要的步数为 dj - bi + 1,比他小的点默认这个值,所以在统计答案的时候可以从后往前,依次遍历

代码

#include<iostream>
#include<cstring>
using namespace std;
const int N = 1e6 + 10,M = 2010;
#define x first
#define y second
typedef pair<int ,int >PII;
PII r[M];
PII s[M];
int f[N];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++)
        scanf("%d%d",&r[i].x,&r[i].y);
    for(int i = 1;i <= m;i++)
        scanf("%d%d",&s[i].x,&s[i].y);
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= m;j++){
            if(r[i].x <= s[j].x && r[i].y <= s[j].y)
                f[s[j].x - r[i].x] = max(f[s[j].x - r[i].x],s[j].y - r[i].y + 1);
        }
    int ans = N;
    for(int i = N - 2;i >= 0;i--){
        f[i] = max(f[i],f[i + 1]);
        ans = min(ans,f[i] + i);
        
    }
    cout<<ans<<endl;
    return 0;
}
 类似资料: