【研一课程】算法设计与分析 FInal OJ解题报告

基于Playwright的在线OJ平台UI自动化测试实战指南 UI自动化测试是现代软件工程中保障Web应用质量的关键实践,其核心原理是通过脚本模拟真实用户操作,对界面交互进行自动化验证。这项技术的核心价值在于提升测试效率、确保回归测试的覆盖率,并能集成到CI/CD流程中实现快速反馈。在Web开发、在线教育、企业级应用等场景中,UI自动化测试对于保障复杂交互系统的稳定性尤为重要。针对在线评测系统这类高度动态、强交互的平台,传统的测试方法面临动态内容加载、富文本编辑器操作、多状态结果判定等挑战。本文聚焦于使用Playwright框架,结合页面对象模型设计模式,构建一套稳健 阅读详情

算法设计与分析 课程 FInal OJ解题报告

第一题Traveler——即AtCoder Beginner Contest 197 E-Traveler Editorial

  • 题意:机器人站在一个一维的数轴的原点位置;有N个球分布在数轴上,这些球所处的位置 X i X_i Xi​不一定是正数,同时每个球都有自己的颜色 C i C_i Ci​, C i C_i Ci​的范围是从1到 N N N;现让机器人触发,按照各球的 C i C_i Ci​递增的顺序把所有小球全部捡起来,最后回到原点!输出,最少需要走多少距离?所有的输入都是整数,各个球的位置各不相同,而同色的球可以有多个~

  • 题目链接:AtCoder Beginner Contest 197 E-Traveler Editorial

  • 题目类型: DP,动态规划。

  • 解题思路:

    • 错误解法①——把所有球从小颜色开始捡,相同的颜色从最左边开始捡。 反例:(数字表示球的颜色,0表示原点) 0 − 1 − 2 − 1 − 2 0-1-2-1-2 0−1−2−1−2,按照①的思路,是走完两个1以后,往左边走捡第一个2,然后往右边走捡第二个2,然后回起点;但实际上,最快的是走完两个1以后,先把最右边的2捡了,然后再回原点0的路上把第一个2给捡了。
    • 错误解法②——在①的基础上,进行分类讨论,分成多种情况来判断当我们把目前颜色捡完了要捡下一个颜色时是往左走还是往右走。实操了以后发现很麻烦,遂罢休。
    • 正确解法:(看题解后理解的( ̄▽ ̄)"…)按照上面的思路,问题最难办的是,当一个颜色的球收集完以后,面对下一组新颜色的球,到底是从最左方向的球开始捡还是从最右方向的球开始捡?同时,这个问题有趣的是,每当我们要进行决策这个问题的时候,之前收集完毕的球(颜色标号小的那些球)是不会影响我们当前的决策的!
      • 所以我们可以用DP来解决此问题——用 d p [ i ] [ [ j ] dp[i][[j] dp[i][[j] 表示从最左边开始( j = 0 j=0 j=0 ) 收完所有 i i i 颜色的球以后,需要最少(注意,是”最少“)走多少步数、或从最右边开始( j = 1 j=1 j=1 ) 收完所有 i i i 颜色的球以后最少需要走多少步数.
        • 定义 c o l o r [ i ] [ 0 ] color[i][0] color[i][0]表示颜色 i i i的球第一个出现的位置,和 c o l o r [ i ] [ 1 ] color[i][1] color[i][1]表示颜色 i i i的球最后出现的位置。
        • 状态转移方程: 可以画画草稿图,可以轻易的得到,每一个颜色的收集结果一共4种情况:上一次从左边收这次从左边收;上一次从右边收这次从左边收;上次从左边收这次从右边收;上次从右边收这次也从右边开始收集球。因此可以得到—— d p [ i ] [ 0 ] = m i n { d p [ i − 1 ] [ 0 ] + a b s ( c o l o r [ i − 1 ] [ 1 ] − c o l o r [ i ] [ 0 ] ) , d p [ i − 1 ] [ 1 ] + a b s ( c o l o r [ i − 1 ] [ 0 ] − c o l o r [ i ] [ 0 ] ) } + c o l o r [ i ] [ 1 ] − c o l o r [ i ] [ 0 ] dp[i][0]=min\{ dp[i-1][0] + abs(color[i-1][1]-color[i][0]), dp[i-1][1] + abs(color[i-1][0]-color[i][0]) \} + color[i][1]-color[i][0] dp[i][0]=min{dp[i−1][0]+abs(color[i−1][1]−color[i][0]),dp[i−1][1]+abs(color[i−1][0]−color[i][0])}+color[i][1]−color[i][0];以及 d p [ i ] [ 1 ] = m i n ( d p [ i − 1 ] [ 0 ] + a b s ( c o l o r [ i − 1 ] [ 1 ] − c o l o r [ i ] [ 1 ] ) , d p [ i − 1 ] [ 1 ] + a b s ( c o l o r [ i − 1 ] [ 0 ] − c o l o r [ i ] [ 1 ] ) ) + c o l o r [ i ] [ 1 ] − c o l o r [ i ] [ 0 ] dp[i][1]=min( dp[i-1][0] + abs(color[i-1][1]-color[i][1]), dp[i-1][1] + abs(color[i-1][0]-color[i][1]) ) + color[i][1]-color[i][0] dp[i][1]=min(dp[i−1][0]+abs(color[i−1][1]−color[i][1]),dp[i−1][1]+abs(color[i−1][0]−color[i][1]))+color[i][1]−color[i][0].
        • 别忘了最后一个颜色的球收集完毕要回到原点!
  • 知识点:c语言里的 a b s ( ) abs() abs() 函数是在头文件stdlib.h里的,并不在cmath里,如果只加入了后者库,调用 a b s ( ) abs() abs() 函数返回值是0.因为默认使用 c m a t h cmath cmath的函数返回值都是double类型的,进行整数求绝对值过程回变成0或其他意想不到的结果!

  • 题外话:

    • 有时候就在纠结,贪心和DP常常分不太清楚,毕竟很多时候思想都是”在当前阶段做最好的选择“,就会有点迷惑。我想了想,我自己的理解是:在这个逻辑上,贪心更侧重于”直接执行更好的选择“,这个”更好“的定义是我们可以从”决策逻辑”、“行为“上就能预见谁更好的,比如“选最大的石头”、“选最大的梨子”;而DP是”在诸多选择中选择最好的那个“,有一种遍历所有结果以后选择更好解的感觉,我们不能从”决策逻辑“、”行为“上提前预见,而是从“结果”上选择结果,所以dp的状态转移方程的min会有很多个值,甚至有一个for语句遍历所有可能然后选择min或max的“更好”的那个!
    • 上面这个问题是“dp和贪心在选择当前解”的思考逻辑上有什么不同?但我有时候还会纠结另一个问题,贪心是“在当前阶段做出最好的选择”,dp在状态转移的时候其实也是基于“在当前阶段做出最好的选择”,那么凭什么贪心算法得到的solution在某些场合是局部最优,而dp却能保证是全局最优呢?我想了想,想出了自己的理解:首先,贪心算法在每个阶段,确实是做出了“当前阶段最好的选择”,但缺陷是,你并不能保证“每一次的当前阶段最优的选择一定能保证所有阶段合拢下也是最优的”,所以贪心算法的本质是 “在之前阶段的局部最优的结果上,进行局部最优的选择,得到下一个局部最优的solution” 的过程。所以在算法理论课上,贪心算法的正确性需要用“数学归纳法”或“反证法”来证明它的正确性,比较麻烦。而DP算法的特点是,它的每一个状态函数 d p [ i − 1 ] dp[i-1] dp[i−1] ,在定义都是“前 i − 1 i-1 i−1 子问题下的最优解”!比如背包问题的 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示的是 i i i大小包装前 j j j个物品的最大容量(最优解)!人家DP的结果函数的这个定义就和贪心不同,它强调了,我们求出来的 i − 1 i-1 i−1 子问题已经是最优了,虽然“我”DP也是“在当前子问题 i i i下做出最优的选择”,但“我”DP能保证这么搞出来的子问题 i i i 也是 “最优解” ,但是贪心算法就没这份底气。因此,DP算法的本质是 “在之前阶段的全局最优的结果上,进行最优的选择(可能看起来也是局部最优),得到的是下一个全局最优的solution” 的过程。当然,DP问题两要素:最优子问题结构、子问题重叠。刚刚这个讨论只针对了第一点。一定要强化理解DP算法的这两个特征。
  • 代码Code:

#include<cstdio>
#include<cstdlib>
#include<vector>
#include<queue>
using namespace std;
#define inf 200005
#define INF 0x3f3f3f3f

int n;
int color[inf][2];
// the accumulation may exceed of int32
long long int dp[inf][2]; //dp[i][0] is the minimum steps after we get every i-color ball from the left, dp[i][1] is the minimum steps after we get every i-color ball from the right
int book[inf];
int main()
{
    int i,j;
    int x,c;
    scanf("%d",&n);
    for(i=1;i<=n;i++)       //init
    {
        color[i][0]=INF;    //the end position of color[i]
        color[i][1]=-INF;   //the begin position of color[i]
    }
    for(i=1;i<=n;i++)        //read data in disorder
    {
        scanf("%d%d",&x,&c);
        book[c]=1;
        if(x<color[c][0])color[c][0]=x; //update the begin position
        if(x>color[c][1])color[c][1]=x; //update the end position
    }

    //begin dp...
    dp[0][0]=dp[0][1]=0;
    for(i=1;i<=n;i++)
    {
        if(!book[i])    // too lazy to introduce a vector to set down which color has shown up. So I take this way~
        {
            dp[i][0]=dp[i-1][0];
            dp[i][1]=dp[i-1][1];
            color[i][0]=color[i-1][0];
            color[i][1]=color[i-1][1];
            continue;
        }
        dp[i][0]=min(dp[i-1][0]+ abs(color[i-1][1]-color[i][0]), dp[i-1][1] + abs(color[i-1][0]-color[i][0]) );
        dp[i][0]+=color[i][1]-color[i][0];
        dp[i][1]=min(dp[i-1][0]+ abs(color[i-1][1]-color[i][1]), dp[i-1][1] + abs(color[i-1][0]-color[i][1]) );
        dp[i][1]+=color[i][1]-color[i][0];
    }
    printf("%lld\n",min(dp[n][0]+abs(color[n][1]),dp[n][1]+abs(color[n][0])));  //return to the origin
    return 0;
}

第二题 Pipes——即Codeforces Round #212 (Div. 2) E Petya and Pipes

  • 题意:给一张有向图构成一个网络流,一共有 N N N个节点,起点是0,汇点是 N − 1 N-1 N−1,以 N × N N \times N N×N的形式输入有向图的矩阵。然后给定一个 K K K,问,可以将任意条pipe的容量增大1或更多,但所有增加的值不能超过 K K K,请问这种情况下的最大流能够是多少?所有管道的容量以及K什么的都是整数!

  • 题目链接:Codeforces Round #212 (Div. 2) E Petya and Pipes

  • 题目类型: 最少费用最大流( Minimum Cost Maximum Flow, MCMF)

  • 题解:

    • 什么是 最简单的最少费用最大流问题呢? 就是每根pipe上流动的flow都会有一个各自规定的费用,而且是按照”单位flow“算价钱的”单位费用“,流得越多花费越多!MCMF问题就是,在实现能够求得最大流的情况下,总费用是最少的!
    • 如何求解最大流问题呢?由给定的网络流的图,转换成”残余网络图“,然后在这个残余网络图上利用边上的残余流量值,跑FF算法或EK算法就行了。注意,总结一个重点:最大流问题是在残余网络上找增广路对应的path然后更新残余网络图!——主要要素是:①在残余网络上;②用边上的residual值;③找增广路的path; ④用path更新残余网络。
    • 那是如何求解MCMF问题呢?由给定的网络流的图,转换成”残余网络图“,然后在这个残余网络图上,利用边上的费用信息,跑最短路算法,寻找一条”从源点到汇点而且是最少费用“的path。注意,这里的重点是:①在残余网络上;②用边上的费用值;③找最短路的path; ④用path更新残余网络。
    • 这题如何转换成MCMF问题呢?题目说可以给任意管子增加 K K K的容量,但是总增加的容量不能超过 K K K,那么就让增加的容量作为费用即可。注意:当两个点之间存在pipe时,才能增加容量,如果两个点之间不存在边,那是不能凭空增加容量的——又不能造管子…( ̄▽ ̄)"
      • 题目给的图读入到内容中,建图时,费用为0!这样算法会优先去跑0费用的管道——即尽量不增加管道的容量。
      • 对于每条存在的pipe,加一条边,容量为 K K K,因为这个管子不可能用超过 K K K次,费用为1。——扩容一格容量就花1费用。
      • 没了,其他都是费用流的板子。每次SPFA都会找出一条最短路(最小费用path),按这个path进行update残余网络值就行了。
    • 注意:当SPFA跑完,而终点的最短路(最小费用)若超过”剩余可增加的管道容量的额度“的话,说明此时已经到达算法结束的时候了!而此时,要单独分别计算”到底能最多增加几个单位容量“来加到结果上!
  • 其他本题的收获: 能够让我学习、巩固最大流、费用流的写法:初始化、边的存储等知识点。其中尤其是边的存储内容,让我收益颇丰。关于此题、以及更基础的费用流的学习思考,详见此【帖子】。

  • 思路参考来源:

  • 代码Code: 这份费用流、最大流的板子甚好,以后可以复用了。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
#define inf 55
//the index is from 0 for the whole code
int n,k;
int s,g;        //begin node and the end node
int path[inf];  //record the path of SPFA

queue<int>q;
int book[inf];      //whether the node is in the queue
int dis[inf];       //cal the shortest distance

struct Edge
{
    int to,res,cost;
    int next;   //to achieve link of edges
    void setEdge(int to,int res,int cost)
    {
        this->to=to;
        this->res=res;
        this->cost=cost;
    }
    void setNext(int next)
    {
        this->next=next;
    }
}edge[4*inf*inf];   //we add our own edges, should have more space (is 4* rather than 2*)
int head[inf];  //the first edge of nodes
int inc;      //the next index for storing edge
void addEdge(int s,int g,int res,int cost)
{
    edge[inc].setEdge(g,res,cost);
    edge[inc].setNext(head[s]);   //the origin head[s]
    head[s]=inc;  //update head[s]: the 'first' edge of node (during storing is the last)
    inc++;
}

bool SPFA()
{
    //init
    memset(book,0,sizeof book);
    memset(path,-1,sizeof path);
    for(int i=0;i<n;i++)dis[i]=INF;
    dis[s]=0;   //don't forget to initial the source node
    //begin
    q.push(s);
    book[s]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        book[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].next)//i is the index of adjacent edges
        {
            int v=edge[i].to;
            // if the edge can use, meaningful to update
            if(edge[i].res>0&&dis[v]>dis[u]+edge[i].cost)
            {
                dis[v]=dis[u]+edge[i].cost;
                path[v]=i;  //record the index of 'the edge' rather than node in path
                if(!book[v])    //each node may be updated by multiple edges. Thus here should be a judgment
                {
                    q.push(v);
                    book[v]=1;
                }
            }
        }
    }
    if(path[g]==-1)return false;
    return true;
}

int MCMF()
{
    int totalCost=0;
    int maxFlow=0;
    while(SPFA())
    {
        int minRes=INF;
        for(int i=g;i!=s;i=edge[path[i]^1].to)  //i is the index of the end node, j is the index of edges
        {
            int j=path[i];
            if(edge[j].res<minRes)minRes=edge[j].res;
        }
        //dis[g] represents the total cost of per res , rather than max res in the path!!! so we should use
        if(minRes*dis[g]+totalCost>k)   //invalid result, the MCMF is over.
        {   //Every given pipes from the origin question is ran out!!!
            maxFlow+=(k-totalCost)/dis[g];  //how many units of flow can we add more.
            break;
        }
        //update the res of edges
        totalCost+=minRes*dis[g];
        maxFlow+=minRes;
        for(int i=g;i!=s;i=edge[path[i]^1].to)  //i is the index of the end node, j is the index of edges
        {
            int j=path[i];
            edge[j].res-=minRes;
            edge[j^1].res+=minRes;
        }
    }
    return maxFlow;
}

int main()
{
    memset(head,-1,sizeof head);    //it's essential to init the head array. Because 'next' of edges array is set by the initial value of head array.
    //read mp
    scanf("%d%d",&n,&k);
    s=0;
    g=n-1;
    //set residual mp
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            int res;
            scanf("%d",&res);
            //the cost of reverse edge is a negative number
            if(res){
                addEdge(i,j,res,0);
                addEdge(j,i,0,0);
                //we add another edge, assume that no pipe no new K
                addEdge(i,j,k,1);
                addEdge(j,i,0,-1);
            }
        }
    //MCMF
    printf("%d\n",MCMF());
    return 0;
}

第三题 Edge Spliting——即 AtCoder GC039 B-Graph Partition

  • 题意: 输入一个无向图, N < 200 N<200 N<200,小图,然后让我们输出,这个图最多可以变成“K分图”,的K是多大?不存在就输出-1.

  • 题目链接: 虽然题意相同,但因为输入数据的格式有点不同,所以我就不贴了~

  • 题目类型: 图论和K分图的理解

  • 题解: 可以参看这个博主的博客——AtCoder GC039 B-Graph Partition——优快云 RSHS

    主要是几点:

    • K分图的定义要搞清楚:三角形不能算三分图,因为这题的定义是K分图之间是串联的,各个set之间不能是环状结构!所以三角形要输出-1.
    • 如果一个图连2分图都满足不了,那肯定K分图也做不到!(二分图是最低要求)。所以先判断是否可以二分图,不行就输出-1.
    • K分图的 K最大是多少,就取决于一张图里的不重复边的情况下,最长path的长度! 即K等于图中最长的path长度加1。可以自己画个图理解一下。例如两个点,一条边,那最长的path就是1,那么最大的K就是2,二分图呗。如何求这个最长path呢,用floyd算法跑一下即可。
  • 代码Code:

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define inf 209
#define INF 0x3f3f3f3f

int n,m;
vector<int>edge[inf];
int mp[inf][inf];
int book[inf];
bool flag=true;

void dfs(int u,int color)
{
    book[u]=color;
    for(int i=0;i<edge[u].size();i++)
    {
        int v=edge[u][i];
        if(book[v]==-1)dfs(v,!color);
        else if(book[v]!=-1&&book[v]!=!color) //not visited
        {
            flag=false;
            return;
        }
    }
}

int main()
{
    int i,j,k;

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            mp[i][j]=INF;
    while(m--)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        edge[u].push_back(v);
        edge[v].push_back(u);
        mp[u][v]=mp[v][u]=1;
    }

    memset(book,-1,sizeof book);
    for(i=1;i<=n;i++)   // whether two-color graph exists
    {
        if(book[i]==-1)
            dfs(i,0);
        if(!flag)
        {
            printf("-1\n");    // not exist bi-partition graph
            return 0;
        }
    }

    //floyd
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j&&mp[i][j]>mp[i][k]+mp[k][j])
                    mp[i][j]=mp[i][k]+mp[k][j];
    int maxV=-INF;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(mp[i][j]!=INF&&mp[i][j]>maxV)
                maxV=mp[i][j];
    printf("%d\n",maxV+1);
    return 0;
}

第四题 Bitcoin Array——即Leetcode 932 Beautiful Array

  • 题意:输入一个数字N,输出由1~N组成的数组的排列情况,要求是对于任何两个数 i < k < j i<k<j i<k<j,这个数组都不存在 A [ k ] × 2 = A [ i ] + A [ j ] A[k] \times 2 = A[i]+A[j] A[k]×2=A[i]+A[j].

  • 题目链接:Leetcode 932 Beautiful Array

  • 题目类型: 分治、构造

  • 解题思路:解题思路网上很多了,所以我就不再此赘述。可以参看各路博客,构造法讲的不错,就是费脑子理解( ̄▽ ̄)"…

  • 经历的bug: 输出格式和 Leetcode 的题目不一样,找了好久bug。

  • 个人理解: 看完他们的思路讲解还是似懂非懂,可以看一份清晰的代码,就懂了,比如看我的( ̄▽ ̄)"…

  • 代码Code: (输出格式和 Leetcode 不同)

#include<cstdio>
#include<vector>
using namespace std;

int n;
vector<int> last;      // store the last solution
vector<int> ans;    // store the now solution

int main()
{
    int i,j,k;
    int len=1;
    last.push_back(1);//initial

    scanf("%d",&n);
    while(1)
    {
        ans.clear();    // clear the vector before every while
        for(i=0;i<last.size();i++) // construct odd numbers
        {
            if(last[i]*2-1<=n) // In case that the number is bigger than n
                ans.push_back(last[i]*2-1);
        }
        for(i=0;i<last.size();i++) // then construct even numbers
        {
            if(last[i]*2<=n)   // In case that the number is bigger than n
                ans.push_back(last[i]*2);
        }
        //move 'ans' to 'e' vector
        last.clear();
        for(i=0;i<ans.size();i++)last.push_back(ans[i]);

        if(ans.size()>=n)break;
    }
    printf("[");
    for(i=0;i<n-1;i++)printf("%d,",ans[i]);
    printf("%d]\n",ans[i]);
    return 0;
}
Python编程进阶:从NOJ作业到算法思维与工程实践 在编程学习中,掌握基础语法只是起点,真正的核心在于培养算法思维和解决复杂问题的能力。算法思维是一种将实际问题抽象为计算模型,并通过逻辑与数据结构高效求解的方法论,其价值在于提升代码的效率、可维护性与可扩展性。在工程实践中,这种思维广泛应用于数据处理、系统优化、自动化脚本等场景。本文以Python编程为例,深入探讨如何通过经典题目训练,将字符串处理、数学模拟、基础算法与数据结构应用等知识融会贯通。文中融入了贪心算法和模拟算法等关键概念,旨在帮助学习者从完成作业的层面,跃升至掌握一类问题解法的层面,为后续深入学 阅读详情

相关推荐

算法竞赛晋级策略:从省赛到国赛的规则解读与备赛优化

算法竞赛作为检验编程与问题解决能力的重要平台,其核心机制通常遵循“区域赛-全国赛”的晋级阶梯。理解竞赛规则不仅是参与的基础,更是制定有效策略的关键。从技术原理上看,竞赛晋级逻辑往往基于排名、名额分配和同分处理规则,这些要素共同决定了选手能否从区域赛突围。在工程实践中,掌握规则细节能帮助选手规避常见误区,例如因误解“赛点排名”或忽略“学校名额限制”而导致的意外出局。本文聚焦于算法竞赛中的典型场景——区域赛优秀排名却无缘全国总决赛,通过分析ICPC、CCPC、蓝桥杯等主流赛事的晋级机制,揭示实力之外的关键变量。

weixin_33901641的博客 503

AtCoder Beginner Contest 179 E.Sequence Sum

AtCoder Beginner Contest 179 E.Sequence Sum 题目链接 一开始以为是矩阵,后来发现就是简单的找循环节,我们可以标记每一个 xxx,我找循环节的思路是这样的: sss 为循环节起点,eee 为终点,sumsumsum 记录前缀和,mapmapmap 标记每一个 xxx~ 因为循环节的元素是唯一的,所以当一个元素出现第二次时,它一定是循环节起点;当一个元素出现第三次时,它前面那个元素一定是循环节终点。注意我们此时是多截取了一个循环节的,所以 sss 和 eee 都需要

旺崽的博客 2707

贪心算法实战:从蓝桥杯“金箍棒高度”题解到算法思维提升

贪心算法是算法设计与分析中的核心思想之一,其核心原理是在每一步选择中都采取当前状态下最优的决策,从而希望导致全局最优解。这种策略在解决最优化问题时,常能提供高效且简洁的解决方案,技术价值在于其出色的时间复杂度和空间效率,尤其适用于具有贪心选择性质和最优子结构的问题。在工程实践中,贪心算法广泛应用于任务调度、数据压缩、图论中的最小生成树和最短路径等场景。本文以蓝桥杯国赛真题“金箍棒高度”为具体案例,深入剖析了如何将实际问题抽象为贪心模型,并严谨证明其正确性。通过这道涉及**高度差**计算和**最优策略**验证

weixin_30911451的博客 469

SCAU 算法设计与分析 OJ复习

8594 有重复元素的排列问题(优先做) 时间限制:1000MS 代码长度限制:10KB 提交次数:1610 通过次数:656 题型: 编程题 语言: G++;GCC;VC;JAVA Description 设集合R={r1,r2,…,rn}是要进行排列的n个元素,其中r1,r2,…,rn可能相同。 试着设计一个算法,列出R的所有不同排列。 即,给定n以及待排的n个可能重复的元素。计算输出n个元素的所有不同排列。 输入格式 第1行是元素个数n,1<=n<=15。接下来的1行是待排列的n个元

Maoxim的博客 2608

蓝桥杯Java B组省赛真题复盘:从环境配置到算法建模的实战指南

LRU缓存、日期计算、迷宫搜索、大数阶乘——这些是算法与工程能力交汇的基础技术概念。其核心原理在于状态建模、边界校验与资源约束下的最优解设计,技术价值体现在高并发鲁棒性、时间复杂度优化及输入不可信前提下的程序稳定性。典型应用场景覆盖竞赛编程、后台服务缓存实现、金融系统日期处理及大数据预处理等。本文基于2024年蓝桥杯Java B组真实考题,深度解析java环境变量配置失误导致的编译失败、JDK17特性误用等高频故障,并结合闰年判定、DFS剪枝、质因数分解等关键知识点,还原考场级工程决策逻辑。

weixin_30245867的博客 456

算法竞赛交互题:从二分猜数到隐藏图探索的实战指南

在算法设计与问题求解中,交互式算法是一种重要的计算模型,它模拟了程序与外部系统通过有限轮次问答进行信息交换的过程。其核心原理在于,程序并非一次性获取全部输入,而是通过精心设计的询问策略,逐步从“黑盒”系统中提取关键信息,从而在询问次数限制下高效解决问题。这种模型具有显著的工程价值,它广泛应用于网络探测、数据库查询优化、自适应测试以及游戏AI等场景,要求开发者不仅掌握算法思想,还需注重通信协议与边界条件处理。本文聚焦于算法竞赛中的交互题,深入剖析了其通信机制、常见题型(如二分猜数、序列重构与图探索)的解题框架

weixin_33859844的博客 350

OJ题目 P1236 夺取宝藏问题(Ipomy)算法设计与分析实践题目

夺取宝藏问题(Ipomy)oj算法设计与分析实践题目,动态规划问题,两种方法,第二种方法,oj可测评通过

mili_j的博客 1695

洛谷新手入门指南:从零到高效刷题的系统方法

在线评测系统(Online Judge, OJ)是算法学习和编程能力训练的核心平台,它通过自动化评测机制为代码提供即时反馈。其工作原理是用户提交代码后,系统在沙箱环境中运行,并与预设的测试用例进行比对,从而判定结果。这种技术对于掌握数据结构与算法、提升编程思维和代码调试能力具有重要价值,广泛应用于编程竞赛、技术面试准备和日常技能训练。在众多OJ平台中,洛谷(Luogu)以其丰富的题库、活跃的社区和强大的社交功能脱颖而出。本文聚焦于**新手入门**和**高效刷题**,旨在帮助初学者快速掌握平台核心功能,建立系

weixin_30457551的博客 513

Auto Design Safety Analysis实操:安全分析如何驱动车身设计决策

在整车开发中,CAE仿真与有限元分析不仅是验证工具,更是驱动设计决策的核心手段。车身结构的安全性能取决于前期拓扑架构与传力路径的合理规划,而碰撞安全分析的价值在于将验证思维切换为设计思维,在造型冻结前通过快速评估与方案对比,让每一次结构变更都有据可依。本文从碰撞工况差异、刚度模态校核、约束系统匹配等基础概念切入,梳理安全分析在车身结构开发中的工程实践路径,涵盖正碰、偏置碰、侧碰等关键场景,并结合焊点失效排查、仿真与试验差异归因等常见问题,探讨如何通过组件化模型管理、自动化脚本与跨团队协同机制,让分析结果真正

weixin_34195142的博客 324

算法设计与分析-以ACM大学生程序设计竞赛在线题库为例

算法设计与分析-以ACM大学生程序设计竞赛

Algorithm2018s-OJ:NJU算法设计与分析2018Spring在线评审。 (Java)

南京大学 算法设计与分析 2018春 OJ 1. 最大子序列和问题 题目描述 给定一整数序列 a1, a2, …, an,求 a1~an 的一个子序列 ai~aj,使得从 ai 到 aj 的和最大。 只需要求出最大子序列的和,而不需要求出最大的那个序列。 输入 一组整数,数字和数字之间以空格隔开。 输出 该整数序列中最大子序列的和 样例输入 -2 11 -4 13 -5 -2 样例输出 20 2. 中位数附近2k+1个数 题目描述 给出一串整型数 a1,a2,...,an 以及一个较小的常数 k,找出这串数的中位数 m 和最接近 m 的小于等于 m 的 k 个数,以及最接近 m 的大于等于 m 的 k 个数。将这 2k+1 个数按升序排序后输出。 中位数定义:如果数串的大小是偶数 2j,中位数是从小到大排列的第 j 个数;如果数串的大小是奇数 2j+1,中位数是从小到大排列的第 j+1 个

LOJ#2351. 「JOI 2018 Final」毒蛇越狱

LOJ#2351. 「JOI 2018 Final」毒蛇越狱 https://loj.ac/problem/2351 分析: 首先有\(2^{|?|}\)的暴力非常好做。 观察到\(min(|1|,|0|,|?|)\le 6\),我们只需要推出一个\(2^{|0|}\)和\(2^{|1|}\)的容斥式子 而这个式子也是很好推的。 考虑子集反演: \(f(S)=\sum\limits_{...

342

springcloud+nacos+gateway+oauth2小聚会

在微服务工程中,Nacos作为目前主流的注册中心和配置中心,Spring Cloud Gateway作为目前主流的网关,下面引入spring security+oauth2+jwt作为认证和授权中心,进行简单的聊聊。

ldcaws的专栏 2646

hrbust/哈理工oj 1126 Final Destination II【矩阵快速幂+递推】

Final Destination II Time Limit: 1000 MS Memory Limit: 65536 K Total Submit: 342(97 users) Total Accepted: 139(75 users) Rating:  Special Judge: No Descripti

mengxiang000000 965

服务器AutoDL自己部署QWen3

说明:核心参数:30B 模型原精度权重文件约 60GB,单张 PRO 6000 拥有 48GB 显存,单卡塞不下原精度模型,2张 PRO 6000 = 96GB 总显存,这不仅能装下模型,还能留出约 30GB 显存给 KV Cache(上下文长度) 以及 Omni 多模态组件 处理图片/视频输入时的额外开销。1. 前提准备模型选择:直接下载到 AutoDL 服务器上=》原精度模型(BF16/FP16) 的 Qwen3-Omni-30B,选择的示例和环境如下。# 3. 正式执行模型下载。

xiaoxiao_00001的博客 414

【问题解决】Python 运行报错 `ModuleNotFoundError` 全网最全解决方案,一文搞定所有导包问题

本文全面解析Python中常见的ModuleNotFoundError和ImportError问题,提供从基础到高级的解决方案。文章首先分析问题原因,包括模块未安装、环境不一致、路径问题等,然后给出7种解决方案:安装缺失模块、检查Python环境、使用虚拟环境、添加搜索路径、相对导入、setup.py安装本地包和使用__init__.py。针对Jupyter Notebook、Docker容器等常见场景提供专门解决方案,并推荐使用requirements.txt、pipenv等预防措施。最后分享调试技巧,帮

博客 914

SpringBoot面试刷题平台开发与毕业设计实践

在线评测系统(Online Judge)是计算机教育领域的重要工具,通过自动化代码评判机制实现编程能力的量化评估。其核心技术在于安全沙箱环境和实时判题系统,采用Docker容器隔离等技术保障系统安全性。在工程实践中,这类系统常应用于算法竞赛、编程教学和面试准备等场景。本文以SpringBoot框架为基础,详细解析如何构建面向面试场景的刷题平台,重点探讨了MyBatis-Plus数据持久化、Docker沙箱隔离等关键技术实现,并分享了毕业设计中架构设计、性能优化等实战经验。对于计算机专业学生而言,此类项目既能

weixin_30522095的博客 399

基于STM32+华为云IOT设计的云平台监控系统_102

本次设计结合现代生活的具体需求,设计出一套基于华为云IOT设计的云平台监控系统,可以远程实时查看家里光照强度、温湿度等信息,支持在云端控制家里的电器设备,实现远程控制。

7643

王道408数据结构高效复习指南:从核心原理到实战应用

数据结构是计算机科学的核心基础,它研究数据的组织、存储和操作方式,其核心原理在于通过抽象数据类型(ADT)定义数据及其操作,并利用算法实现高效处理。理解其技术价值在于,它是构建高效软件系统的基石,直接影响程序的性能和可扩展性。在工程实践中,数据结构知识广泛应用于数据库索引、操作系统调度、网络路由等关键场景。对于备考计算机专业考研,特别是针对408统考科目,掌握数据结构不仅是应对考试的关键,更是提升计算思维和解决复杂问题能力的核心。本文聚焦于如何高效复习数据结构,结合王道考研课程体系,深入探讨从知识框架构建到

weixin_30336061的博客 428

【OpenClaw从入门到精通】第19篇:OpenClaw电商实战:从零搭建比价+库存监控+自动调价全自动化系统(2026实测附完整代码)

2026年OpenClaw成为全球最火开源项目,电商行业因其场景高频、数据标准化成为其核心落地领域。本文针对电商从业者面临的比价繁琐、库存混乱、调价滞后三大痛点,基于OpenClaw的“接入层-执行层-决策层”三层架构,从零拆解智能比价、多平台库存监控、动态自动调价三大核心场景的实现逻辑。文中包含完整的环境配置、技能安装、代码实现(含Python脚本与YAML配置)、执行结果验证,同时补充关键算法原理与避坑指南,兼顾新手入门与进阶提升。读者可直接参考本文实操流程,快速搭建属于自己的电商自动化系统,实现7×2

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 2238

23、工业物流中的多智能体路径规划与碰撞处理策略

本文探讨了工业4.0背景下工业物流中的多智能体路径规划(MAPF)与碰撞处理策略。分析了自动导引车(AGV)等移动资源的应用现状,综述了主流路径规划算法如A*、D*Lite、M*等,以及集中式与分布式碰撞检测方法。重点比较了五种碰撞避免策略:路径交叉、优先级、起始时间调整、无交叉路径和速度调整,提出了基于环境条件的策略选择流程,并通过流程图展示了评估、组合、测试与优化的全过程。文章强调应根据订单不确定性、时间约束、优先级和生产组织等因素综合选择或组合策略,以提升物流效率与系统可靠性。

mac99的博客 125

loj3014 「JOI 2019 Final」独特的城市(长链剖分的妙用)

长链剖分的一个妙用。

一位蒟蒻的小博客 559

电脑硬件:电脑主板上的接口介绍,看完你就懂了

它们主要用于连接老式的键盘和鼠标,虽然速度和兼容性不如USB接口,但在某些特定场合依然发挥着重要作用。PCIe接口是主板上的扩展能力象征,可以连接各种扩展卡,如显卡、声卡、网卡等。电脑主板作为电脑硬件组成关键的部分,今天给大家分享一下电脑主板上有哪些接口,具体每一个接口的特点、使用场景,有需要的朋友可以来了解一下!它们不仅能连接鼠标、键盘、U盘、打印机,还能连接各种外设,如移动硬盘、游戏手柄等。:虽然现在用得越来越少,但在一些特定场合,如工业控制、老旧设备上,仍然需要使用PS/2接口。

IT技术分享社区 2786

蓝桥杯JavaB组赛题复盘:从解题心路到实战策略的深度解析

算法竞赛是检验编程思维与工程实践能力的重要场景,其核心在于将复杂问题通过数据结构和算法模型进行高效求解。理解问题本质、掌握经典算法原理是解题的基础,例如动态规划、深度优先搜索和二分查找等,它们为解决最优化、搜索类问题提供了通用框架。这些技术的价值在于能够将指数级复杂度优化至多项式级别,从而应对大规模数据处理需求。在算法竞赛如蓝桥杯中,高效的问题建模、稳健的代码实现与科学的考场策略,共同决定了最终成绩。本文结合【蓝桥杯JavaB组】赛题实例与【解题心路】历程,深入剖析从读题抽象、算法选型到调试优化的全流程,并

weixin_33904756的博客 412

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

华为OD机试:图论与动态规划结合的算法题解析

图论与动态规划是算法设计中的两大核心技术,广泛应用于路径优化、资源调度等领域。Dijkstra算法作为经典的单源最短路径算法,通过优先队列实现高效搜索;而状态压缩DP则利用位运算高效处理必经点遍历问题。在工业级场景如物流调度、网络安全中,组合使用这两种技术能有效解决带约束的最优路径问题。以华为OD机试真题为例,题目要求在多检查点约束下寻找安全系数乘积最大的路径,这需要将Dijkstra算法改造为处理乘积优化,并结合状态压缩记录检查点访问状态。Java的BigDecimal和Go的math/big包为处理大数

weixin_30252709的博客 449

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

上一篇: 【算法设计】最短路理解+费用流入门学习初步小结
下一篇: 【Chips】如何启动第一个Quartus/Vivado下的Verilog仿真过程
仰天倀笑
博客等级 码龄10年 313粉丝 124原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值