算法整理

算法代码索引:

代码1:矩阵快速幂求斐波那契

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int MOD=10000;

struct mat
{
    ll a[2][2];
};

mat mat_mul(mat x,mat y)
{
    mat res;
    memset(res.a,0,sizeof(res.a));
    for(int i=0; i<2; i++)
        for(int j=0; j<2; j++)
            for(int k=0; k<2; k++)
                res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j])%MOD;
    return res;
}
void mat_pow(int n)
{
    mat c,res;
    c.a[0][0]=c.a[0][1]=c.a[1][0]=1;
    c.a[1][1]=0;
    memset(res.a,0,sizeof(res.a));
    for(int i=0; i<2; i++) res.a[i][i]=1;
    while(n)
    {
        if(n&1) res=mat_mul(res,c);
        c=mat_mul(c,c);
        n>>=1;
    }
    printf("%d\n",res.a[0][1]);
}

int main()
{
    int n;
    while(~scanf("%d",&n)&&n!=-1)
    {
        mat_pow(n);
    }
    return 0;
}

代码2:多重背包的二维写法

for (int i = 1; i <= n; ++i) {
        for (int j = 0; j <= capacity; ++j) {
            // 如果不选择第 i 个物品
            dp[i][j] = dp[i - 1][j];
            // 如果选择第 i 个物品(可以选择多次)
            if (j >= weights[i - 1]) {
                dp[i][j] = max(dp[i][j], dp[i][j - weights[i - 1]] + values[i - 1]);
            }
        }
    }

代码3:LCS

for(int i=1;i<=n;i++)
{
    for(int j=1;j<=n;j++)
    {
        if(a[i]==b[j])dp[i][j]=dp[i-1][j-1]+1;//如果说a串的第i位和b串的第j位一样,那么就为dp[i-1][j-1]的LCS+1
        else dp[i][j]=max(dp[i][j-1],dp[i-1][j]);//如果不一样,就从dp[i-1][j],dp[i][j-1]中取一个最大值
    }
}

代码4:完全背包的递归写法

#include <stdio.h>
#define MAX_ITEMS 100
// 全局变量定义
int val[MAX_ITEMS] = {60, 100, 120}; // 物品价值
int wt[MAX_ITEMS] = {10, 20, 30};    // 物品重量
int n = 3;                           // 物品数量

// 返回a和b中较大的值
int max(int a, int b) {
    return (a > b) ? a : b;
}

// 完全背包问题的递归函数
int knapsack_unbounded_recursive(int W, int idx) {
    // 基础情况:没有物品或者背包容量为0
    if (idx == 0 || W == 0)
        return 0;

    // 如果当前物品的重量大于背包容量,则当前物品不能放入背包
    if (wt[idx - 1] > W)
        return knapsack_unbounded_recursive(W, idx - 1);

    // 递归调用:当前物品选或不选,取两者中的最大值
    return max(val[idx - 1] + knapsack_unbounded_recursive(W - wt[idx - 1], idx), knapsack_unbounded_recursive(W, idx - 1));
}

// 示例
int main() {
    int W = 50;
    printf("%d\n", knapsack_unbounded_recursive(W, n)); // 输出:300
    return 0;
}

代码5:网络流

EK算法:

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int N=1e3+9;
int flow[N];//源点到当前点的流量
int pre[N];//上一条的增广是哪一条链(增广路径中每个点的前驱)
int mp[N][N];//描述图
queue<int>qu;
int n,m;
int bfs(int s,int t)//找路径
{
    while(!qu.empty())qu.pop();
    memset(pre,-1,sizeof(pre));
    pre[s]=0;
    flow[s]=inf;
    qu.push(s);//源点塞进去
    while(!qu.empty())
    {
        int p=qu.front();
        qu.pop();
        if(p==t)break;//如果到了汇点,一定是边最少的先到达汇点
        for(int i=1;i<=n;i++)//这里是完成一个链
        {
            if(i!=s&&mp[p][i]>0&&pre[i]==-1)
            {
                pre[i]=p;
                flow[i]=min(flow[p],mp[p][i]);//流的最大值
                qu.push(i);
            }
        }
    }
    if(pre[t]==-1)return -1;
    return flow[t];//返回流
}
int ek(int s,int t)
{
    int delta=0,tot=0;
    while(1)
    {
        delta=bfs(s,t);
        if(delta==-1)break;
        int p=t;
        while(p!=s)
        {
            mp[pre[p]][p]-=delta;//正向
            mp[p][pre[p]]+=delta;//反向路
            p=pre[p];//每一个点前面的点,相当于不停的前移
        }
        tot+=delta;//把每次找到的增广加起来
    }
    return tot;
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(mp,0,sizeof(mp));
    memset(flow,0,sizeof(flow));
    int u,v,w;
    while(m--)
    {
       scanf("%d%d%d",&u,&v,&w);
       mp[u][v]+=w;
    }
    printf("%d\n",ek(1,n));
    return 0;
}

最小费用最大流:

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int N=1e5+9;
int vis[N];
int n,m,s,t;
struct node
{
    int t,net,flow,dis;    
}e[N];
int maxflow=0,mincost=0;
int head[N],tot,flow[N],last[N],dis[N],pre[N];
void add(int x,int y,int f,int d)
{
    e[tot].t=y;
    e[tot].flow=f;
    e[tot].dis=d;
    e[tot].net=head[x];
    head[x]=tot++;
}
bool spfa(int s,int t)
{
    queue<int>qu;
    memset(dis,inf,sizeof(dis));
    memset(flow,inf,sizeof(flow));
    memset(vis,0,sizeof(vis));
    qu.push(s);
    vis[s]=1;
    dis[s]=0;
    pre[t]=-1;
    while(!qu.empty())
    {
        int now=qu.front();
        qu.pop();
        vis[now]=0;
        for(int i=head[now];i!=-1;i=e[i].net)
        {
            int b=e[i].t;
            if(e[i].flow>0&&dis[b]>dis[now]+e[i].dis)
            {
                dis[b]=dis[now]+e[i].dis;
                pre[b]=now;
                last[b]=i;
                flow[b]=min(flow[now],e[i].flow);
                if(!vis[b])
                {
                    vis[b]=1;
                    qu.push(b);
                }
            }
        }
    }
    return pre[t]!=-1;
}
void dinic()
{
    while(spfa(s,t))
    {
        int x=t;
        maxflow+=flow[t];
        mincost+=flow[t]*dis[t];
        while(x!=s)
        {
            e[last[x]].flow-=flow[t];
            e[last[x]^1].flow+=flow[t];
            x=pre[x];
        }
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d%d%d",&n,&m,&s,&t);
    int x,y,z,f;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&x,&y,&z,&f);
        add(x,y,z,f);
        add(y,x,0,-f);
    }
    dinic();
    printf("%d %d\n",maxflow,mincost);
    return 0;
}
posted @   wlqtc  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示