2021.11.4

上午模拟赛 50+10+0+0

第一题贪心写法    

 T、2

注意到要求的是距离的最⼩值的最⼤值。 ⽐较容易想到的是⼆分答案 x, 判定是否能找到⼀条最⼩值不⼩于x的路径。等价于对 每个引⼒柱做⼀个半径为 x 的圆,判定是否能⾛到终点。 在这⼀限制下⼩w不能⾛到的区域,肯定是由若⼲个距离2x的障碍和上下边界组 成。那么实际上就是求最⼩⽣成树上上边界到下边界的路径上最⼤边。需要求 n 个点 n^2 条边的最⼩⽣成树,kruskal 是 n^2logn 的,可以获得 80 分,prim算法 n^2, 期望得到满分。

 

T4 

  区间dp+优化

今日学习内容:dp

       √1.背包dp      01,完全,多重,分组,依赖性

       √2.区间dp      合并石子

        3.树形dp     

        4.状压dp(初状态的确定)

       √5.线性dp

       √6.棋盘dp

       √7.其他常用dp模板:最长上升子序列,最长公共子序列,最大权值正方形,最大全            0/全1正方形,最大连续子段和,期望dp,概率dp

    8.dp优化

int lingyibeibao() {
    for(int i=0; i<n; i++)
        for(int j=m; j>=w[i]; j--)
            dp[j]=max(dp[j],dp[j-w[i]]+u[i]);
}
int wanquanbeibao() {
    for(int i=0; i<n; i++)
        for(int j=w[i]; j<=m; j++)
            dp[j]=max(dp[j],dp[j-w[i]]+u[i]);
}
int duochongbeibao() {
    for(int i=0; i<n; i++)
        for(int k=0; k<p[i]; k++)
            for(int j=m; j>=w[i]; j--)
                dp[j]=max(dp[j],dp[j-w[i]]+u[i]);

}
int fenzubeibao() {
    for(int i=1; i<=n; i++)
        for(int j=0; j<=m; j--)
            for(int k=1; k<=s[i]; k++) //s[i]表示第i组物品的个数
                if(j>=v[i][k]) { //剩余的背包容量j大于第i组的第k个物品的体积
                    f[i][j] = max(f[i][j],f[i-1][j-v[i][k]]+w[i][k]);
                }
}
int yilaibeibao() {
    int dfs(int u) {
        /*说明是用户*/
        if(u>(n-m)) {
            f[u][1] = val[u];
            return 1;//用户个数
        }
        int sum = 0,now;
        for(int i=head[u]; i!=-1; i=edge[i].next) {
            int v = edge[i].v;
            now = dfs(v);//以v为根节点的子树有多少个用户
            sum+=now;
            for(int j=sum; j>=0; j--)
                for(int k=1; k<=now; k++) {
                    if(j>=k)
                        f[u][j] = max(f[u][j],f[u][j-k]+f[v][k]-edge[i].w);//edge[i].w是u到v的花费
                }
        }
        return sum;
    }
}
int qvjiandp() {
    for(int len = 1; len<=n; len++) { //枚举长度
        for(int j = 1; j+len<=n+1; j++) { //枚举起点,ends<=n
            int ends = j+len - 1;
            for(int i = j; i<ends; i++) { //枚举分割点,更新小区间最优解
                dp[j][ends] = min(dp[j][ends],dp[j][i]+dp[i+1][ends]+something);
            }
        }
    }
}
int zuichangshangshengzixvlie() {
    for(int i=2; i<=n+1; i++) {
        int num=0;
        for(int j=i-1; j>=1; j--)
            if(a[i]>a[j])
                num=max(num,dp[j]);

        dp[i]=num+1;
    }
}
int zuichanggonggongzixvlie() {
    char s[MAX],t[MAX];
    scanf("%s%s",s,t);
    int x=strlen(s),y=strlen(t);
    for(i=0; i<x; i++) {
        for(j=0; j<y; j++) {
            if(s[i]==t[j])
                dp[i][j]=dp[i-1][j-1]+1;
            else
                dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
        }
        printf("%d\n",dp[i][j]);
    }
}
int zuichanggonggongshangshengzixvlie() {
    for (int i=1; i<=n; ++i) {
        int val=0;//val是决策集合S(i,j)中f[i-1][k]的最大值
        for(int j=1; j<=m; ++j) {
            //原来的k循环+判断+状态转移

            if (a[i]==b[j])
                f[i][j]=val+1;
            else
                f[i][j]=f[i-1][j];

            if (b[j]<a[i])
                val=max(val,f[i-1][j]);

            //j即将增大为j+1,检查j能否进入新的决策集合
        }
    }
}
int levenshtien() {
    char a[N], b[N];
    int dp[N][N];
    int main() {
        scanf("%s%s", a, b);
        int aLen = strlen(a);
        int bLen = strlen(b);

        //极端情况
        for (int i = 1; i <= aLen; i++) //以i+1来考虑第i个字符的情况
            dp[i][0] = i;
        for (int j = 1; j <= bLen; j++) //以j+1来考虑第j个字符的情况
            dp[j][0] = j;

        for (int i = 1; i <= aLen; i++) { //以i+1来考虑第i个字符的情况
            for (int j = 1; j <= bLen; j++) { //以j+1来考虑第j个字符的情况
                if (a[i - 1] == b[j - 1]) //相同时距离不变
                    dp[i][j] = dp[i - 1][j - 1];
                else //不同时取三个位置的最小值再+1
                    dp[i][j] = min(dp[i - 1][j - 1],min(dp[i - 1][j], dp[i][j - 1])) + 1;
            }
        }
        printf("%d\n", dp[aLen][bLen]);

        return 0;
    }
}
int zuidaquanyizhengfangxing() {
    int ans=0;
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            if(a[i][j]==0) {
                dp[i][j]=0;
            } else {
                dp[i][j]=min(min(dp[i-1][j-1],dp[i-1][j]),dp[i][j-1])+1;
            }
            ans=max(ans,dp[i][j]);
        }
    }
    printf("%d\n",ans);
}
int zuidalianxvziduanhe() {
    const int inf = 0x7fffffff;
    int num[101];
    int N;
    cin >> N;
    for(int i=0; i<N; i++)
        cin >> num[i];
    int ans = -inf;
    for(int i=0; i<N; i++)
        ans = max(ans,num[i]);
    if(ans <= 0)
        cout << ans << endl;
    else {
        int sum =0;
        for(int i=0; i<N; i++) {
            if(sum + num[i] < 0)
                sum = 0;
            else
                sum += num[i];
            ans = max(ans,sum);
        }
        cout << ans << endl;
    }
}

    ps:未学完内容在锦集里,别忘了!

posted @ 2021-11-04 16:18  kanateta  阅读(39)  评论(0)    收藏  举报