基础dp1

kuangbin套题 基础dp1

原先分配任务时dp并非我负责,但是最近比赛表明数论选手的压力太大,于是决定开坑从零自学dp。
听缪神说kuangbin套题能很快提升水平,那不多说,开搞吧。
链接: kuangbin带你飞 专题12 基础dp1.

dp

Dynamic Programming,动态规划。用于决策问题,在贪心无法贪到最优解的情况下,如果能找到一种无后效性的决策方法,就可以尝试用dp进行求解。
某个方面来说dp和暴力其实有异曲同工之处。


A - Max Sum Plus Plus

多组数据,输入直到文件结束。每一行有一个n和一个m,以及由n的数字组成的序列。要求从其中挑出m段连续且不重复的序列,使他们的和最大。

转移方程
dp[i][j]=max(dp[i][j-1],max(dp[i-1][k]))+a[j] (i-1 <= k <= j-1)

转移方程不是很难写,但是内存卡得有点难受。
用Max把max (dp[i-1][k])记录下来,然后二维滚一维。
代码:

#include "bits/stdc++.h"
using namespace std;
int dp[100005];
int Max[100005];
//dp[i][j]=max(dp[i][j-1],max(dp[i-1][k]))+a[j] (i-1 <=  k <= j-1)
int main(){
    //freopen("std1.in","r",stdin);
    //freopen("std1.out","w",stdout);
    int n,m;
    while(~scanf("%d%d",&m,&n)){
        int ans=-0x3f3f3f3f;
        for(int i=0;i<=m;i++)
            Max[i]=-0x3f3f3f3f,dp[i]=-0x3f3f3f3f;
        Max[0]=0;
        for(int i=1;i<=n;i++){
            int tmp;
            scanf("%d",&tmp);
            for(int j=m;j>=1;j--){
                dp[j]=max(dp[j],Max[j-1])+tmp;
                Max[j]=max(Max[j],dp[j]);
            }
            ans=max(ans,dp[m]);
        }
        printf("%d\n",ans);
    }


}

B - Ignatius and the Princess IV

找出一串数字中出现次数过半的数字。
应该会打代码的都会做吧,直接跳过。


C - Monkey and Banana

给与一个n,再给予n种积木,每种积木都有长宽高三个数值, 允许旋转木块,将木块搭高,要求下方的木块的长宽严格大于上放的木块,问最高高度是多少?

首先将一个木块的旋转结果拆成6种无法旋转的木块,这样就不需要考虑木块的旋转了,然后对宽度(高度)进行排序,这样排在前面的木块定不会放在之后的木块之下,满足了无后效性。

转移方程: dp[i]=max(dp[i],dp[j]+h[i]);
代码:

#include "bits/stdc++.h"
using namespace std;
const int inf =0x3f3f3f3f;
typedef struct {
    int x,y,z;
}BLOCK;
vector<BLOCK> d;
int dp[1200];
int main(){
    int n,tot=0;
    while(scanf("%d",&n),n){
        tot++;
        memset(dp,0,sizeof(dp));
        d.clear();
        d.push_back({inf,inf,0});
        for(int i=1;i<=n;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            d.push_back({a,b,c});
            d.push_back({a,c,b});
            d.push_back({b,a,c});
            d.push_back({b,c,a});
            d.push_back({c,a,b});
            d.push_back({c,b,a});
        }
        sort(d.begin(),d.end(),[](BLOCK a,BLOCK b){
            if(a.x!=b.x)
                return a.x>=b.x;
            else
                return a.y>=b.y;
        });
        int nn=6*n,ans=0;
        for(int i=1;i<=nn;i++){
            dp[i]=d[i].z;
            for(int j=1;j<i;j++){
                if(d[i].x<d[j].x&&d[i].y<d[j].y){
                    dp[i]=max(dp[i],dp[j]+d[i].z);
                    ans=max(ans,dp[i]);
                }
            }
        }
        printf("Case %d: maximum height = %d\n",tot,ans);
    }
}

D - Doing Homework (状态压缩)

给一个n(n<15),之后给n个作业,每个作业有一个截止时间和一个完成时间,每次交作业如果超过了截止时间,会扣(提交时间-截止时间)的分数,问按什么顺序做扣分最少?

把作业是否完成的状态用二进制表示,完成用1未完成用0,那么可以用一个不大于2^15的数字表示所有的作业状态。
如果状态从小跑到大,那么跑每一个状态之前一定会跑过所有的可能到这个情况的状态。那么只要枚举每一个为1的位置,去其中的最小值就是当前情况的最优解。

转移方程:
dp[i]=max(dp[i],dp[i-1<<j]+time)
time = dp[i-1<<j].time + work[j].t - work[j].d;
j=1,2,3,…,n && (i & 1<<j) ==1
代码:

#include "bits/stdc++.h"
using namespace std;
const int inf =0x3f3f3f3f;
struct {
    string s;
    int d,t;
}work[20];
struct {
    int time,from,val;
}dp[1<<16];
int main() {
    int tot;
    scanf("%d",&tot);
    while(tot--){
        int n; scanf("%d",&n);
        for(int i=1;i<=(1<<n)-1;i++)
            dp[i].val=0x3f3f3f3f;
        for(int i=0;i<n;i++){
            char tmp[150];
            int a,b;
            scanf("%s%d%d",tmp,&a,&b);
            work[i]={tmp,a,b};
        }
        for(int i=0;i<= (1<<n)-1;i++) {
            for (int j = n-1; j >= 0; j--) {
                if (i & (1 << j)) {
                    int t = i - (1 << j);
                    int time = dp[t].time + work[j].t - work[j].d;
                    if (max(time,0) + dp[t].val < dp[i].val) {
                        dp[i].val = max(time,0) + dp[t].val;
                        dp[i].time = dp[t].time+work[j].t;
                        dp[i].from = j;
                    }
                }
            }
        }
        stack<int> s;
        int t=(1<<n)-1;
        while(t){
            s.push(dp[t].from);
            t-=(1<<dp[t].from);
        }
        printf("%d\n",dp[(1<<n)-1].val);
        while(!s.empty()){
            printf("%s\n",work[s.top()].s.data());
            s.pop();
        }
    }
}

E - Super Jumping! Jumping! Jumping!

给一个n和有n的数字组成的数列,要求从左往右选择,每次选择的数字严格大于上次选择的数字,问如何选择使选择的数字和最大。

基本线性dp,只需要两个循环即可。因为每个数字都可以是第一个被选择的数字,所以只需要在开头额外放一个数值为0的点即可。
转移方程:
dp[i]=max(dp[i],dp[j]+in[i])
in[j]<in[i]
代码:

#include "bits/stdc++.h"
using namespace std;
int dp[2000];
int in[2000];
int main(){
    int n;
    while(scanf("%d",&n),n){
        memset(dp,0,sizeof(dp));
        int ans=0;in[0]=-0x3f3f3f3f;
        for(int i=1;i<=n;i++){
            scanf("%d",&in[i]);
            for(int j=0;j<i;j++){
                if(in[i]>in[j]){
                    dp[i]=max(dp[i],dp[j]+in[i]);
                    if(dp[i]>ans)
                        ans=dp[i];
                }
            }
        }
        printf("%d\n",ans);
    }
}

F - Piggy-Bank (背包问题)

先给一个T表示T组数据,每一个组数据开头一个m1,m2,表示钱的重量和(猪(存钱罐)和钱)的重量的重量(其实减一下就行了),然后给一个n表示有n种钱,接下来n行表示这种钱的面额和这种钱的重量。问面额最小是多少,不可能则输出Impossible.

完全背包问题(该死,背包也好久没写了)。
空间开二维dp[i][j],i表示处于取第i种钱币的情况,j表示当前使用的空间容量。
二维转一维滚空间后的转移方程:
dp[i]=min(dp[i],dp[i-ob[j].h]+ob[j].m);
代码:

//define int long long 纯粹是懒人写法
#include "bits/stdc++.h"
using namespace std;
#define int long long
int dp[100050];
struct OB{
   int m,h;//money,heavy
}ob[5050];
signed main(){
   int tot;
   scanf("%lld",&tot);
   while(tot--){
       int a,b,h,n;
       scanf("%lld%lld",&a,&b);
       h=b-a;
       scanf("%lld",&n);
       for(int i=1;i<=h;i++)dp[i]=0x3f3f3f3f3f3f3f3f;
       dp[0]=0;
       for(int i=1;i<=n;i++){
           scanf("%lld%lld",&a,&b);
           ob[i]={a,b};
       }
       for(int i=1;i<=h;i++){
           for(int j=1;j<=n;j++){
               if(i-ob[j].h>=0){
                   dp[i]=min(dp[i],dp[i-ob[j].h]+ob[j].m);
               }
           }
       }
       if(dp[h]!=0x3f3f3f3f3f3f3f3f){
           printf("The minimum amount of money in the piggy-bank is %lld.\n",dp[h]);
       }else
           printf("This is impossible.\n");

   }
}
G - 免费馅饼 (数塔问题)

中文题面就不放题意了

开一个二维空间,dp[i][j],i表示时间,j表示位置,在所有有饼的位置将dp[i][j]++,然后从i=100000跑到i=0,最后dp[0][5]就是答案。(如果把每一个位置都右移一位,就不需要考虑0越界的问题)
转移方程:
dp[i][j]=dp[i][j]+max(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1]);
代码:

#include <bits/stdc++.h>
using namespace std;
int dp[100500][20];
int main(){
   int n;
   while(scanf("%d",&n),n){
      memset(dp,0,sizeof(dp));
       for(int i=1;i<=n;i++){
           int a,b;
           scanf("%d%d",&a,&b);
           dp[b][a+1]++;
       }
       int ans=0;
       for(int i=100000;i>=0;i--){
           for(int j=1;j<=11;j++){
               dp[i][j]=max(dp[i+1][j],max(dp[i+1][j-1],dp[i+1][j+1]))+dp[i][j];
           }
       }
       printf("%d\n",dp[0][6]);
   }
}

H - Tickets

先给一个T表示T组数据,然后给一个n表示人数,接下来一行有n个数字,表示给n个人单独买票的时间,下一行是n-1个数字表示相邻的两个人一起买票的时间。问这n个人怎么样最快买完票。

基本线性dp.时间算过了,到不了第二天,那有手就行。
转移方程:
dp[i]=max(dp[i-1]+s[i],dp[i-2]+d[i-1]);
代码:

#include <bits/stdc++.h>
using namespace std;
int s[2500],d[2500];//single double
int dp[5000];
int main(){
   int tot;
   scanf("%d",&tot);
   while(tot--){
       int n;
       memset(dp,0,sizeof(dp));
       scanf("%d",&n);
       for(int i=1;i<=n;i++){
           scanf("%d",&s[i]);
       }
       dp[1]=s[1];
       for(int i=1;i<n;i++){
           scanf("%d",&d[i]);
       }
       for(int i=2;i<=n;i++){
           dp[i]=min(dp[i-1]+s[i],dp[i-2]+d[i-1]);
       }

       int ts=dp[n]%60,fs=(dp[n]/60)%60,fh=8+dp[n]/60/60 ;
       bool flag=true;
       if(fh>=12){
           flag=false;
           fh-=12;
       }
       printf("%02d:%02d:%02d ",fh,fs,ts);
       if(flag)
           printf("am\n");
       else
           printf("pm\n");

   }
}

I - 最少拦截系统
emm这题我也不知道算不算个dp。。。找个拦截策略。。。

每次都拿已有系统中从低到高的去尝试拦截,拦不住加系统
转移方程:我也不知道是啥。
代码:

#include <bits/stdc++.h>
using namespace std;
vector<int> ans;
int main(){
    int n;
    while(~scanf("%d",&n)){
        ans.clear();
        int tmp,cmt=0;
        scanf("%d",&tmp);
        ans.push_back(tmp);
        for(int i=2;i<=n;i++){
            scanf("%d",&tmp);
            int k=-1,MAX=0x3f3f3f3f;
            for(int j=0;j<ans.size();j++){
                if(ans[j]>=tmp&&ans[j]<MAX){
                    MAX=ans[j];
                    k=j;
                }
            }
            if(k==-1)
                ans.push_back(tmp);
            else{
                ans[k]=tmp;
            }
        }
        printf("%d\n",ans.size());
    }
}

J - FatMouse’s Speed

输入直到文件结束,一行给两个值,一个是老鼠的体重,一个是老鼠的速度,要求选择其中的数个,使体重严格上升,速度严格上升,问怎么选选的最多?

排序,简单线性dp
代码

#include<bits/stdc++.h>
using namespace  std;
typedef pair<int,int> pii;
typedef pair<pair<int,int>,int> piii;
vector<pair<pair<int,int>,int> > in;
typedef pair<int,int> pii;
#define MAXN 500000
int dp[MAXN];
int sel[MAXN];
stack<int> out;
int main(){
    int a,b;
    int id=0,tot;

    while(~scanf("%d%d",&a,&b)){
        id++;
        in.push_back({{a,b},id});
    }
    for(int i=0;i<id;i++)sel[i]=-1;
    sort(in.begin(),in.end(),[](piii a,piii b){
        if(a.first.first!=b.first.first){
            return a.first.first<b.first.first;
        }else
            return a.first.second>=b.first.second;
    });
    for(int i=0;i<id;i++){
        for(int j=0;j<i;j++){
            if(in[j].first.first<in[i].first.first&&in[j].first.second>in[i].first.second&& (dp[j]+1>dp[i]))
                dp[i]=max(dp[i],dp[j]+1),sel[i]=j;
        }
    }
    int ans=-1,ma=-0x3f3f3f3;
    for(int i=0;i<id;i++){
        if(dp[i]>ma)
            ma=dp[i],ans=i;
    }
    while(ans!=-1){
        out.push(in[ans].second);
        ans=sel[ans];
    }
    printf("%d\n",out.size());
    while(!out.empty()){
        printf("%d\n",out.top());
        out.pop();
    }
}

K

假装自己写出来了


L - Common Subsequence (LCS)

最长公共子板子题吧

dp[i][j],i表示在第一个字符串的位置,j表示在第一个字符串的位置
转移方程 d p [ i ] [ j ] = m a x { d p [ i − 1 ] [ j ] d p [ i ] [ j − 1 ] d p [ i − 1 ] [ j − 1 ] + 1 s 1 [ i ] = = s 2 [ j ] dp[i][j]=max\left\{ \begin{array}{rcl} dp[i-1][j] \\ dp[i][j-1] \\ dp[i-1][j-1] + 1 & & {s1[i]==s2[j]} \end{array} \right. dp[i][j]=maxdp[i1][j]dp[i][j1]dp[i1][j1]+1s1[i]==s2[j]
代码:

#include "stdio.h"
#include "cstring"
#include "algorithm"
using namespace std;
#define MAXN 1000
char s1[MAXN],s2[MAXN];
int dp[MAXN][MAXN];
int main(){
    s1[0]='k',s2[0]='k';
    while(~scanf("%s%s",s1+1,s2+1)){
        memset(dp,0,sizeof(dp));
        int len1=strlen(s1)-1,len2=strlen(s2)-1;
        for(int i=1;i<=len1;i++){
            for(int j=1;j<=len2;j++){
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                if(s1[i]==s2[j])
                    dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
            }
        }
        printf("%d\n",dp[len1][len2]);
    }
}
M - Help Jimmy

中文题面题意不解释了

还是简单线性dp吧,除了繁一点没啥,dp[i][j],i代表第i个板子,j=1是从左边落下,j=2是从右边落下,末尾特判。唯一要留心的地方是上一块板子会被下一块挡住。
转移方程:
dp[i][1]=min(dp[i][1],dp[j][1]+t1);
(t1表示从第j块左端到第i块左端,以下类推)
dp[i][2]=min(dp[i][2],dp[j][1]+t2);
dp[i][1]=min(dp[i][1],dp[j][2]+t1);
dp[i][2]=min(dp[i][2],dp[j][2]+t2);
代码:

#include "stdio.h"
#include "cstring"
#include "algorithm"
using namespace std;
#define MAXN 10050
struct  BOAD{
    int x1,x2,y;
}in[MAXN];
bool cmp(BOAD a,BOAD b){
return a.y>b.y;
}
const int inf = 0x3f3f3f3f;
int dp[MAXN][3];//左 右
bool flag[MAXN][3] ;
int main(){
    int tot;
    scanf("%d",&tot);
    while(tot--){
        int n,x,y,MAX;
        scanf("%d%d%d%d",&n,&x,&y,&MAX);
        memset(flag,0,sizeof(flag));
        for(int i=1;i<=n+1;i++)
            dp[i][1]=dp[i][2]=0x3f3f3f3f;
        dp[0][1]=dp[0][2]=0;

        for(int i=1;i<=n;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            in[i]={a,b,c};
        }
        sort(in+1,in+1+n,cmp);
        n++;
        in[0]={x,x,y};
        in[n]={-inf,0x3f3f3f3f,0};
        for(int i=1;i<=n;i++){
            for(int j=0;j<i;j++){
                int t=-in[i].y+in[j].y;
                if(t<=0||t>MAX)
                    continue;
                if(in[j].x1>=in[i].x1&&in[j].x1<=in[i].x2&&!flag[j][1]){
                    flag[j][1]=true;
                    int t1=t,t2=t;
                    if(i!=n){
                        t1+=in[j].x1-in[i].x1;
                        t2+=in[i].x2-in[j].x1;
                    }
                    dp[i][1]=min(dp[i][1],dp[j][1]+t1);
                    dp[i][2]=min(dp[i][2],dp[j][1]+t2);
                }

                if(in[j].x2>=in[i].x1&&in[j].x2<=in[i].x2&&!flag[j][2]){
                    flag[j][2]=true;
                    int t1=t,t2=t;
                    if(i!=n){
                        t1+=in[j].x2-in[i].x1;
                        t2+=in[i].x2-in[j].x2;
                    }
                    dp[i][1]=min(dp[i][1],dp[j][2]+t1);
                    dp[i][2]=min(dp[i][2],dp[j][2]+t2);
                }
            }
        }
        printf("%d\n",dp[n][1]);
    }
}

N - Longest Ordered Subsequence(LIS)

最长上升子板子题,没啥好说的,可以优化,但是我懒
代码:

#include<stdio.h>
#include "algorithm"

using namespace std;
int dp[10050],in[10050];
int main(){
    in[0]=-1;
    int n,ans=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&in[i]);
        for(int j=0;j<i;j++){
            if(in[i]>in[j]){
                dp[i]=max(dp[i],dp[j]+1);
            }
            ans=max(ans,dp[i]);
        }
    }
    printf("%d\n",ans);
}

O - Treats for the Cows(区间DP)

给一个n,然后给一个由n个数组成的序列,每次只能从首或尾取值,值为取得 次数*原值 ,问如何取值最大。

用递归的思路做,从取完开始还原,比较到当前状态是补上左值更优还是右值更优。

转移方程:
dp[x][y]=max(dp[x+1][y]+in[x]*[n-y+x],dp[x][y - 1] + in[y] * (n - y + x));
代码:

#include "stdio.h"
#include "algorithm"
using namespace std;
int dp[2005][2005];
int in[2005];
int n;
int getdp(int x,int y){
    if(x==y) return dp[x][x]=n*in[x];
    if(dp[x][y])return dp[x][y];
    return dp[x][y]=max(getdp(x+1,y)+in[x]*(n-y+x),getdp(x,y - 1) + in[y] * (n - y + x));
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&in[i]);
   printf("%d\n",getdp(1,n));
}

p

Q - Phalanx

线性dp,不过是把一维换成二维
从左下角到右上角开始判断能否成立,时间还是挺宽裕的
代码:

#include <bits/stdc++.h>
using namespace std;
char in[3000][3000];
int dp[3000][3000];
void main(){
    int n;
    while(scanf("%d",&n),n){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                dp[i][j]=1;
        for(int i=1;i<=n;i++)
            scanf("%s",in[i]+1);
        int ans=1;
        for(int i=n-1;i>=1;i--){
            for(int j=2;j<=n;j++){
                int len=dp[i+1][j-1];
                for(int k=1;k<=len;k++){
                    if(i+k>n||j-k<1||in[i+k][j]!=in[i][j-k]) {
                        break;
                    }
                    else {
                        dp[i][j]++;
                        ans=max(dp[i][j],ans);
                    }

                }
            }
        }
        printf("%d\n",ans);
    }
}
R - Milking Time

给一个n(没用),m,r,然后给m行,每行有一个时间段和权重,选择的时间段不能重叠,且间隔至少为r,问怎么选择可以使权重和最大?

简单线性dp。。。排个序套套公式就ok

代码:

#include "stdio.h"
#include "algorithm"
#include "vector"
#include<cstring>
using namespace std;
#define MAXN 100000
typedef pair<pair<int,int>,int> pii;
vector<pair<pair<int,int>,int> > in;
bool cmp(pii a,pii b){
    if(a.first.second!=b.first.second)
        return  a.first.second<b.first.second;
    return a.first.first<b.first.first;
}
int dp[MAXN];
void solve(){
    int n,m,r,ans=0;
    while(~scanf("%d%d%d",&n,&m,&r)){
        ans=0;
        memset(dp,0,sizeof(dp));
        in.clear();
        for(int i=1;i<=m;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            in.push_back({{a,b+r},c});
        }
        in.push_back({{0,0},0});
        sort(in.begin(),in.end(),cmp);
        for(int i=1;i<=m;i++){
            for(int j=0;j<i;j++){
                if(in[i].first.first>=in[j].first.second)
                    dp[i]=max(dp[i],dp[j]+in[i].second);
            }
            if(in[i].first.second-r<=n)
                ans=max(ans,dp[i]);
        }
        printf("%d\n",ans);
    }
}

int main(){
    solve();
}

S

好烦啊,不想讲了
代码:
#include “stdio.h”
#include “algorithm”

using namespace std;
#define MAXN 2050
int lsh[MAXN],num[MAXN];
int cnt;
void LSH(int n){
for(int i=1;i<=n;i++)
lsh[i]=num[i];
sort(lsh+1,lsh+1+n);
cnt=unique(lsh+1,lsh+n+1)-lsh-1;
for(int i=1;i<=n;i++)
num[i]=lower_bound(lsh+1,lsh+cnt+1,num[i])-lsh;
}
long long dp[MAXN][MAXN];
int main(){
//freopen(“std1.in”,“r”,stdin);
// freopen(“std1.out”,“w”,stdout);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
LSH(n);
//dp[i][j]=min(dp[i-1][k])+ num[i]-j
for(int i=1;i<=cnt;i++)
dp[0][i]=0x3f3f3f3f3f3f3f3f;
dp[0][1]=0;
long long out1=0x3f3f3f3f3f3f3f3f;
for(int i=1;i<=n;i++){
for(int j=1;j<=cnt;j++){
if(j!=1)
dp[i][j]=min(dp[i-1][j],dp[i][j-1]-abs(lsh[num[i]]-lsh[j-1]))+abs(lsh[num[i]]-lsh[j]);
else
dp[i][j]=dp[i-1][1]+abs(lsh[num[i]]-lsh[j]);
if(i==n)
out1=min(out1,dp[i][j]);
}
}

long long out2=0x3f3f3f3f3f3f3f3f;
dp[0][1]=0x3f3f3f3f3f3f3f3f;
dp[0][cnt]=0;
for(int i=1;i<=n;i++){
    for(int j=cnt;j>=1;j--){
        if(j!=cnt)
            dp[i][j]=min(dp[i-1][j],dp[i][j+1]-abs(lsh[num[i]]-lsh[j+1]))+abs(lsh[num[i]]-lsh[j]);
        else
            dp[i][j]=dp[i-1][cnt]+abs(lsh[num[i]]-lsh[j]);
        if(i==n)
            out2=min(out2,dp[i][j]);
    }
}


printf("%lld\n",min(out1,out2));

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值