首页 > 其他分享 >NFLS 240422 比赛总结

NFLS 240422 比赛总结

时间:2024-04-24 13:00:47浏览次数:23  
标签:ch 240422 比赛 int 机器人 NFLS char st getchar

PieOrDolphin

Topcoder SRM617-Div1-Lv2

题意

有 \(n\ (\leq50)\) 个人,给他们发礼物,共有 \(m\ (\leq1000)\) 天,每天要给两个人发礼物,其中一个人获得一号礼物,另一个获得二号礼物,定义一个方案的总和为每个人获得的一号二号礼物数之差的和。现在每一天要发礼物的两个人已经确定,但是你可以选择给谁发一号或二号礼物,构造方案使得总和最小。

思路

将每一天的礼物方案抽象为一条边,获得一号礼物的人向获得二号礼物的人连一条有向边,因此每个人的出度即为获得一号礼物数,入度同理为二号礼物数,那么我们的目标即为通过确定每一条边的方向来最小化每个点入度出度之差。直接遍历并直接确定方向十分困难,我们考虑不断贪心反转边来寻找更优的答案,具体来说,考虑到对于一条简单路径,如果反转路径上所有边,那么路径上除了首尾端点的其他点不会受到影响(原先的一个出度变为入度,原先的一个入度变为出度),而首端点则出度 \(-1\),入度 \(+1\),尾端点反之。因此,我们每次找到出入度之差 \(\geq2\) 的点 \(st\),以 \(outd[i]-ind[i]\geq 2\) 的情况为例,我们再找到另外一个 \(ind[i]-outd[i]\geq 1\)[1] 的点 \(ed\),将 \(st\) 到 \(ed\) 简单路径的全部边反转即可,为了方便处理,对于 \(ind[i]-outd[i]\geq 2\) 的情况,直接将整张图反转,再用相同方法处理。

代码

#include<bits/stdc++.h>
using namespace std;
#ifdef ONLINE_JUDGE
#define getchar __getchar
inline char __getchar(){
    static char ch[1<<20],*l,*r;
    return (l==r&&(r=(l=ch)+fread(ch,1,1<<20,stdin),l==r))?EOF:*l++;
}
#endif
template<class T>inline void rd(T &x){
    T res=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while('0'<=ch && ch<='9'){res=res*10+ch-'0';ch=getchar();}
    x=res*f;
}
template<class T>inline void wt(T x,char endch='\0'){
    static char wtbuff[20];
    static int wtptr;
    if(x==0){
        putchar('0');
    }
    else{
        if(x<0){x=-x;putchar('-');}
        wtptr=0;
        while(x){wtbuff[wtptr++]=x%10+'0';x/=10;}
        while(wtptr--) putchar(wtbuff[wtptr]);
    }
    if(endch!='\0') putchar(endch);
}
const int MAXN=1e3+5,MAXM=55;
typedef pair<int,int> pii;
int n,ans[MAXN],ind[MAXM],oud[MAXM];//ans[i]=1正向,2逆向
pii gift[MAXN];
inline void solve(){
    int st,ed,cur;
    pii pre[MAXM];
    while(1){
        st=-1;ed=-1;
        for(int i=0;i<50;i++){
            if(abs(ind[i]-oud[i])>=2){
                st=i;break;
            }
        }
        if(st==-1) return;
        if (ind[st]>oud[st]){
            for(int i=1;i<=n;i++) ans[i]=3-ans[i];
            for (int i=0;i<50;i++) swap(ind[i],oud[i]);
        }
        fill(pre,pre+50,make_pair(-1,-1));
        queue<int>q;q.push(st);
        while(!q.empty()){
            cur=q.front();q.pop();
            if(ind[cur]>oud[cur]){
                ed=cur;break;
            }
            for(int i=1,u,v;i<=n;i++){
                u=gift[i].first;v=gift[i].second;
                if(ans[i]==2) swap(u,v);
                if(u==cur && v!=st){
                    if(pre[v].first==-1){
                        pre[v]=make_pair(u,i);
                        q.push(v);
                    }
                }
            }
        }
        cur=ed;
        int nxt;
        while(pre[cur].first!=-1){
            nxt=pre[cur].first;
            ans[pre[cur].second]=3-ans[pre[cur].second];
            ind[cur]--;
            oud[cur]++;
            ind[nxt]++;
            oud[nxt]--;
            cur=nxt;
        }
    }
}
int main(){
    rd(n);
    for(int i=1;i<=n;i++){
        rd(gift[i].first);
        oud[gift[i].first]++;
    }
    rd(n);
    for(int i=1;i<=n;i++){
        rd(gift[i].second);
        ind[gift[i].second]++;
    }
    fill(ans+1,ans+1+n,1);

    solve();

    for(int i=1;i<=n;i++){
        wt(ans[i],' ');
    }
    // int cnt=0;
    // for(int i=0;i<50;i++){
    //     cnt+=abs(ind[i]-oud[i]);
    // }
    // cout<<cnt<<endl;
    return 0;
}

CtuRobots

Topcoder SRM647-Div1-Lv2

题意

有 \(n\ (\leq 500)\) 个机器人,每个机器人的价格为 \(cost_i\ (\leq 10^4)\),油箱容量为 \(cap_i\ (\leq 10^9)\),一单位燃料可以走一单位距离,你可以给购买的机器人编号,机器人 \(k\) 可以给机器人 \(k+1\) 补充燃料,但是任意时刻机器人的燃料不能超过其油箱容量上限,你有 \(B\ (\leq 10^4)\) 的预算,购买一些机器人,机器人从 \(0\) 出发,问所有机器人最终都能返回初始点的前提下,能探索到的最大距离。

思路

Tips: 题目并没有对于“速度”进行规定,也就是说,只要距离限制满足,可以视为一台机器人可以在任何时刻到某个地方,不过这个性质并不影响做题

子问题 1

假设我们已经知道了所有已经购买的机器人,如何计算能够探索的最大距离?一个显然的思路是我们只需要油箱最大的机器人进行探索任务,而其他的机器人的任务只是给它补充燃料,两个机器人同时执行探索任务只会浪费燃料没有任何好处。并且我们可以发现,对于某台负责补充燃料的机器人 \(i\),它的最佳选择是在 \(\large\frac{cap_i}{3}\) 处给下一个机器人提供燃料并返航,因为如果小于这个节点时可提供的燃料大于可被接收的燃料造成浪费,而大于这个节点自己会消耗额外的燃料。而且一个很巧妙的性质在于在 \(\large\frac{cap_i}{3}\) 处给下一个机器人补充燃料后,下一个机器人刚好回满。因此我们只需要将机器人的油箱容量从小到大排序,设 \(f_i\) 为机器人 \(i\) 的实际续航时间,有递推关系:\(\large f_1=cap_1,f_2=\frac{f_1}{3}+cap_2,\dots,f_i=\frac{f_{i-1}}{3}+cap_i\),而能探索到的最大距离便为油箱最大的机器人 \(k\) 的续航除以 \(2\) 即 \(\large\frac{f_k}{2}\)。

子问题 2

如何购买机器人使得探索距离最大?我们对于刚才的递推关系再加上预算的限制,就可以 DP 了,首先将机器人按油箱大小排序,设 \(f[i][j]\) 表示前 \(i\) 个机器人可选,预算为 \(j\) 时最大可能的续航(由于还要返程所以答案为 \(f[i][j]/2\)),每次的决策为判断是否购买第 \(i\) 个机器人。

代码

#include<bits/stdc++.h>
#define getmax(x,y) x=max(x,y)
using namespace std;
#ifdef ONLINE_JUDGE
#define getchar __getchar
inline char __getchar(){
    static char ch[1<<20],*l,*r;
    return (l==r&&(r=(l=ch)+fread(ch,1,1<<20,stdin),l==r))?EOF:*l++;
}
#endif
template<class T>inline void rd(T &x){
    T res=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while('0'<=ch && ch<='9'){res=res*10+ch-'0';ch=getchar();}
    x=res*f;
}
typedef double db;
const db eps=1e-8;
const int MAXN=505,MAXB=1e4+5;
int n,bud;
db f[MAXN][MAXB];
struct BOT{
    int cost;
    db cap;
    bool operator < (const BOT& b){
        return cap<b.cap;
    }
}bt[MAXN];
int main(){
    rd(bud);
    rd(n);
    for(int i=1;i<=n;i++){
        rd(bt[i].cost);
    }
    rd(n);
    for(int i=1;i<=n;i++){
        rd(bt[i].cap);
    }
    sort(bt+1,bt+1+n);
    for(int i=1;i<=n;i++){
        memcpy(f[i],f[i-1],sizeof(f[i]));
        for(int j=bt[i].cost;j<=bud;j++){
            getmax(f[i][j],f[i-1][j-bt[i].cost]/3+bt[i].cap);
        }
    }
    cout<<fixed<<setprecision(8)<<f[n][bud]/2.0<<endl;
    return 0;
}

PathGame

Topcoder SRM637-Div1-Lv2

题意

\(2\) 行若干列的方格图,格子为黑色\((\#)\)或白色\((.)\),Snuke 与 Sothe 轮流在上面把白格涂黑,如果有一条从左到右的白色路径,游戏继续,否则游戏结束且最后涂色的玩家判输,保证初始有路径,双方皆用最优策略,判断最后胜者。

思路

我们记录 \(f[l][r][i]\) 为长度为 \(i\) 的全白格的 \(SG\) 函数,\(l,r\) 分别表示左右端只能从上方出发\((0)\),只能从下方出发\((1)\),上下均可出发\((2)\),列举长度为 \(1\) 时最基本的情况赋初值,枚举长度,再枚举中间的断点(涂黑的块)进行转移,显然中间涂黑块所在列 \(SG\) 函数为 \(0\),而左右两边的子块已在长度更小的情况下处理过,因此根据 \(SG\) 定理异或在一起即可。最后将原方格图根据黑格分段,求亦或和即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
int n,f[3][3][MAXN];
string s[3];
bitset<MAXN>ava;
int main(){
    cin>>n>>s[1]>>s[2];
    n=s[1].size();
    f[0][1][1]=0;
    f[1][0][1]=0;
    f[0][0][1]=1;
    f[2][0][1]=1;
    f[2][1][1]=1;
    f[0][2][1]=1;
    f[1][2][1]=1;
    f[1][1][1]=1;
    f[2][2][1]=1;
    for(int i=2;i<=n;i++){
        for(int l=0;l<=2;l++){
            for(int r=0;r<=2;r++){
                ava.reset();
                for(int j=0;j<i;j++){
                    if(!((j==0&&l==1)||(j==i-1&&r==1))) ava[f[l][0][j]^f[0][r][i-j-1]]=1;
                    if(!((j==0&&l==0)||(j==i-1&&r==0))) ava[f[l][1][j]^f[1][r][i-j-1]]=1;
                }
                for(int j=0;j<=n;j++){
                    if(!ava[j]){
                        f[l][r][i]=j;
                        break;
                    }
                }
            }
        }
    }
    int ans=0,lasti=-1,lastdir=2;
    for(int i=0;i<n;i++){
        if(s[1][i]=='#') ans^=f[lastdir][1][i-lasti-1],lasti=i,lastdir=1;
        else if(s[2][i]=='#') ans^=f[lastdir][0][i-lasti-1],lasti=i,lastdir=0;
    }
    ans^=f[lastdir][2][n-lasti-1];
    if(ans!=0) puts("Snuke");
    else puts("Sothe");
    return 0;
}

  1. 为什么尾端点只需要 \(\geq 1\) 即可?因为只要尾端点有差值,反转后最坏情况尾端点无贡献,但是首端点一定有贡献,这样做才能找到所有可能的贡献 ↩︎

标签:ch,240422,比赛,int,机器人,NFLS,char,st,getchar
From: https://www.cnblogs.com/SkyNet-PKN/p/18155046

相关文章

  • 20240422打卡
    第九周第一天第二天第三天第四天第五天第六天第七天所花时间9h代码量(行)727博客量(篇)1知识点了解完成了地铁查询系统的App......
  • 软工计算一 20240422
    1.python中的iter()函数迭代子Python中的iter()函数是内置函数,它负责创建一个迭代器。这个函数接受两个参数:第一个参数是准备转换为迭代器的对象。第二个参数是一个可选的sentinel对象,它用于迭代器中的next()方法,当迭代器到达sentinel值时会停止迭代。基本用法......
  • 2024年GPLT团体程序设计比赛L2-D吉利矩阵题解
    只能说比赛时前期做得太慢了,后面导致题目只能捞点分数(IOI赛制),当时这道题是我不剪枝DFS拿了4分,压线拿铜牌!考完试一做,发现是个大水题(bushi)主要原理:DFS(深度优先搜索)+剪枝名言:学搜索核心就是学剪枝废话不说了,见代码点击查看代码//原理:DFS+剪枝#include<bi......
  • “百度杯”CTF比赛 九月场-123
    “百度杯”CTF比赛九月场123题目类型:web题目描述:12341234,然后就解开了,打开靶机是一个会员登陆界面:解题方法:先查看一下网页源码:这里说用户信息都在user.php里面,然后我们访问一下user.php:发现并没有任何信息扫描一下它的目录文件看一下:扫出了一个user.php和view.php,但......
  • 【比赛】高一下二调 2
    事实证明打水题我还是有一手的T1排座位100Pts题面算是个签到题。直接暴力模拟,只要这个数不在自己的位置上就交换一次即可。赛后题解中有另一种做法:证明的话,数学奥赛的老师也没有具体的办法抽象,但确实是对的。代码#include<bits/stdc++.h>usingnamespacestd;......
  • 【比赛】高一下二调2
    下载题解其实是一道水题,但容易想偏,如以为是逆序对点击查看代码#include<bits/stdc++.h>#definelllonglongusingnamespacestd;constintN=1e6;intn,a[N+5],b[N+5],ans;intmain(){ freopen("seat.in","r",stdin); freopen("seat.out","w&......
  • 最近比赛的wp
    RE复现login_system这个函数就是判断username,点进去发现是线性方程,用z3解fromz3import*s=Solver()a=[0]*16foriinrange(16):a[i]=Int('a'+"["+str(i)+"]")s.add(a[2]+a[1]+a[0]+a[3]==447)s.add(101*a[2]+a[0]+9*a[1]+8*a[3]==12265)s.add(5*a......
  • “百度杯”CTF比赛 2017 二月场-爆破-3
    “百度杯”CTF比赛2017二月场爆破-3题目类型:web题目描述:打开靶机,得到一段php代码,说明这是一道php代码审计类型的题:<?phperror_reporting(0);session_start();require('./flag.php');if(!isset($_SESSION['nums'])){$_SESSION['nums']=0;$_SESSION['time�......
  • CF 比赛记录
    byTheBigYellowDuck包括比赛题以及整场刷了的题。1336(Div.1)CF1336ALinovaandKingdom最直接的想法是按照深度从大到小选,然而选一个非叶子节点会使得其子树内所有点的贡献\(-1\)。那么我们把所有点按照\(dep_u-sz_u\)从大到小排序,选前\(k\)大的即可。时间复杂度......
  • 利用AGI技术为足球比赛制定战术方案
    足球比赛的战术安排对于比赛结果有着决定性的影响。随着技术的发展,AGI(ArtificialGeneralIntelligence)的应用在足球战术分析和制定中扮演着越来越重要的角色。本文将以英超Big6之一的球队为例,探讨如何利用AGI技术分析即将进行的比赛,并帮助主教练制定有针对性的战术方案。注:笔......