暑假专题3,状压DP 区间DP

状压DP

A - Corn Fields POJ3254

Description
Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can’t be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.
Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.

Input
Line 1: Two space-separated integers:
M and
N

Lines 2…
M+1: Line
i+1 describes row
i of the pasture with
N space-separated integers indicating whether a square is fertile (1 for fertile, 0 for infertile)

Output
Line 1: One integer: the number of ways that FJ can choose the squares modulo 100,000,000.

Sample Input
2 3
1 1 1
0 1 0
Sample Output
9
Hint
Number the squares as follows:

1 2 3
4

There are four ways to plant only on one squares (1, 2, 3, or 4), three ways to plant on two squares (13, 14, or 34), 1 way to plant on three squares (134), and one way to plant on no squares. 4+3+1+1=9.

基础的状压DP,用二进制表示每一行的状态,dp时检测是否合法
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define mod 1000000000
int dp[13][1<<13],n,m,ma[13],t;
int check(int j){
    return !(j&(j<<1));
}
int jud(int j,int k){
    return !(j&k);
}
int main(){
    while(scanf("%d %d",&m,&n)!=EOF){
        memset(dp,0,sizeof(dp));
        memset(ma,0,sizeof(ma));
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++){
                scanf("%d",&t);
                if(t)   ma[i]=(ma[i]|(1<<j));
            }
        for(int i=0;i<m;i++){
            for(int j=0;j<(1<<n);j++){
                if(((ma[i]|j)==ma[i])&&check(j)){
                    //printf("%d %d %d\n",i,j,ma[i]);
                    if(i==0){
                        dp[i][j]=1;
                        continue;
                    }
                    for(int k=0;k<(1<<n);k++){
                        if(jud(j,k))
                            dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;
                    }
                }
            }
        }
        int ans=0;
        for(int i=0;i<(1<<n);i++)
            ans=(ans+dp[m-1][i])%mod;
        printf("%d\n",ans);
    }
    return 0;
}

B - 炮兵阵地 POJ1185

Description

司令部的将军们打算在NM的网格地图上部署他们的炮兵部队。一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:

在这里插入图片描述

如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。

现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。

Input

第一行包含两个由空格分割开的正整数,分别表示N和M;

接下来的N行,每一行含有连续的M个字符(‘P’或者’H’),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。

Output

仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。

Sample Input
5 4
PHPP
PPHH
PPPP
PHPP
PHHP

Sample Output	
6
一道经典题目,同样的是用二进制表示每一行的状态0表示为平原,1表示为山地,再枚举每一行的合法状态及其对应炮台数并储存下来,即满足这一行每一个炮台都不会打到对方的状态储存下来,不超过60种
dp[i][j][k]表示第i行为j状态,i-1行为k状态下的最大炮台数,第一行和第二行要额外枚举
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int ma(int a,int b){return a>b?a:b;}
int mi(int a,int b){return a<b?a:b;}
int a[111],dp[111][111][111],sta[100],tot,ans,m,n,num[111];
void init(){
    int i,j;
    for(i=0;i<(1<<m);i++){//获得状态数
        if(((i<<2)&(i<<1))==0&&(i&(i<<1))==0&&(i&(i<<2))==0)
        sta[tot++]=i;
    }
    for(i=0;i<tot;i++)//获得炮台数
        for(int j=0;j<m;j++)
            if(sta[i]&(1<<j))
                num[i]++;
}
int main(){
    char c;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        getchar();
        for(int j=0;j<m;j++){
            scanf("%c",&c);
            if(c=='H')  a[i]=a[i]|(1<<j);
        }
    }
    init();
    int i,j,k,l;
    for(i=0;i<tot;i++)//第一行
    {
        if((a[0]&sta[i])==0){
            dp[0][i][0]=ma(dp[0][i][0],num[i]);
            ans=ma(dp[0][i][0],ans);
        }
    }
    if(n>=2)
    for(i=0;i<tot;i++)//第二行
    {
        for(j=0;j<tot;j++)
        if((a[1]&sta[i])==0&&(sta[i]&sta[j])==0&&(a[0]&sta[j])==0){
            dp[1][i][j]=ma(dp[1][i][j],dp[0][j][0]+num[i]);
            //if(sta[j]==9&&sta[i]==2)    printf("%d\n",dp[1][i][j]);
            ans=ma(dp[1][i][j],ans);
        }
    }
    //printf("%d\n",ans);
    for(i=2;i<n;i++){//剩余行数
        for(j=0;j<tot;j++){
            if((a[i]&sta[j])==0){
                for(k=0;k<tot;k++){
                    if((a[i-1]&sta[k])==0&&(sta[j]&sta[k])==0){
                        for(l=0;l<tot;l++){
                            if((sta[l]&a[i-2])==0&&(sta[l]&sta[k])==0&&(sta[l]&sta[j])==0){
                                dp[i][j][k]=ma(dp[i][j][k],dp[i-1][k][l]+num[j]);
                                ans=ma(dp[i][j][k],ans);
                            }
                        }
                    }
                }
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

C - Hie with the Pie POJ3311

Description

The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unfortunately, due to cutbacks, they can afford to hire only one driver to do the deliveries. He will wait for 1 or more (up to 10) orders to be processed before he starts any deliveries. Needless to say, he would like to take the shortest route in delivering these goodies and returning to the pizzeria, even if it means passing the same location(s) or the pizzeria more than once on the way. He has commissioned you to write a program to help him.

Input

Input will consist of multiple test cases. The first line will contain a single integer n indicating the number of orders to deliver, where 1 ≤ n ≤ 10. After this will be n + 1 lines each containing n + 1 integers indicating the times to travel between the pizzeria (numbered 0) and the n locations (numbers 1 to n). The jth value on the ith line indicates the time to go directly from location i to location j without visiting any other locations along the way. Note that there may be quicker ways to go from i to j via other locations, due to different speed limits, traffic lights, etc. Also, the time values may not be symmetric, i.e., the time to go directly from location i to j may not be the same as the time to go directly from location j to i. An input value of n = 0 will terminate input.

Output

For each test case, you should output a single number indicating the minimum time to deliver all of the pizzas and return to the pizzeria.

Sample Input

3
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
0
Sample Output
8

状压dp的简单TSP问题,先Foloyd求出任意两点的最小距离
dp[i][j]表示在i状态下留在j城市的最小距离,每个状态的二进制串的1表示经过了那座城市
dp[i][k]=min(dp[i][k],dp[i^(1<<(k-1))][t]+d[t][k]);,在i状态留在k点的距离
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
int ma(int a,int b){return a>b?a:b;}
int mi(int a,int b){return a<b?a:b;}
int dis[12][12],n,dp[1<<12][12];
int main(){
    while(scanf("%d",&n)!=EOF&&n){
        int i,j,k;
        for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
                scanf("%d",&dis[i][j]);
        for(k=0;k<=n;k++)//Foloyd求最短距离
            for(i=0;i<=n;i++)
                for(j=0;j<=n;j++)
                    dis[i][j]=mi(dis[i][j],dis[i][k]+dis[k][j]);
        memset(dp,inf,sizeof(dp));
        for(i=1;i<(1<<n);i++){
            for(j=1;j<=n;j++){
                if(i&(1<<(j-1))){//经过第j个城市并留在j城市
                    if(i==(1<<(j-1)))
                        dp[i][j]=dis[0][j];
                    else{
                        for(k=1;k<=n;k++){//取途中的点,类似于Foloyd
                            if(k!=j&&(i&(1<<(k-1))))
                               dp[i][j]=mi(dp[i][j],dp[i^(1<<(j-1))][k]+dis[k][j]);
                        }
                    }
                }
            }
        }
        int ans=inf;
        for(i=1;i<=n;i++){
            ans=mi(ans,dp[(1<<n)-1][i]+dis[i][0]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

D - Islands and Bridges MathJax to parse formulas POJ2288

Description

Given a map of islands and bridges that connect these islands, a Hamilton path, as we all know, is a path along the bridges such that it visits each island exactly once. On our map, there is also a positive integer value associated with each island. We call a Hamilton path the best triangular Hamilton path if it maximizes the value described below.

Suppose there are n islands. The value of a Hamilton path C1C2…Cn is calculated as the sum of three parts. Let Vi be the value for the island Ci. As the first part, we sum over all the Vi values for each island in the path. For the second part, for each edge CiC
i+1 in the path, we add the product ViV
i+1. And for the third part, whenever three consecutive islands CiC
i+1C
i+2 in the path forms a triangle in the map, i.e. there is a bridge between Ci and C
i+2, we add the product Vi
V
i+1*V
i+2.

Most likely but not necessarily, the best triangular Hamilton path you are going to find contains many triangles. It is quite possible that there might be more than one best triangular Hamilton paths; your second task is to find the number of such paths.

Input

The input file starts with a number q (q<=20) on the first line, which is the number of test cases. Each test case starts with a line with two integers n and m, which are the number of islands and the number of bridges in the map, respectively. The next line contains n positive integers, the i-th number being the Vi value of island i. Each value is no more than 100. The following m lines are in the form x y, which indicates there is a (two way) bridge between island x and island y. Islands are numbered from 1 to n. You may assume there will be no more than 13 islands.

Output

For each test case, output a line with two numbers, separated by a space. The first number is the maximum value of a best triangular Hamilton path; the second number should be the number of different best triangular Hamilton paths. If the test case does not contain a Hamilton path, the output must be `0 0’.

Note: A path may be written down in the reversed order. We still think it is the same path.

Sample Input

2
3 3
2 2 2
1 2
2 3
3 1
4 6
1 2 3 4
1 2
1 3
1 4
2 3
2 4
3 4

Sample Output

22 3
69 1

dp[s][i][j]表示在s状态下从i走到j再由j走完全部的点的价值
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
int ma(int a,int b){return a>b?a:b;}
int mi(int a,int b){return a<b?a:b;}
int t,m,n,x,y;
int dp[1<<14][15][15],e[15][15],v[15];
long long num[1<<14][15][15];
int main(){
    scanf("%d",&t);
    while(t--){
        memset(e,0,sizeof(e));
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)   scanf("%d",&v[i]);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            e[x][y]=1; e[y][x]=1;
        }
        if(n==1)    {printf("%d 1\n",v[n]); continue;}
        int i,j,k,s;
        memset(dp,-1,sizeof(dp));
        memset(num,0,sizeof(num));
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            if(i!=j&&e[i][j]==1){
                dp[1<<(i-1)|1<<(j-1)][i][j]=v[i]*v[j]+v[i]+v[j];
                num[1<<(i-1)|1<<(j-1)][i][j]=1;
            }
        for(s=7;s<(1<<n);s++)
            for(i=1;i<=n;i++){
                if((s&(1<<(i-1)))==0)   continue;
                for(j=1;j<=n;j++){
                    if((s&(1<<(j-1)))==0||i==j||!e[i][j])   continue;
                    for(k=1;k<=n;k++){
                        if((s&(1<<(k-1)))==0||i==k||j==k||!e[j][k]) continue;
                        int ss=s-(1<<(i-1));
                        if(dp[ss][j][k]==-1)    continue;
                        int tem=v[i]*v[j]+v[i];
                        if(e[i][k])
                            tem=tem+v[i]*v[j]*v[k];
                        if(dp[s][i][j]<dp[ss][j][k]+tem){
                            dp[s][i][j]=dp[ss][j][k]+tem;
                            num[s][i][j]=num[ss][j][k];
                        }
                        else if(dp[s][i][j]==dp[ss][j][k]+tem)
                            num[s][i][j]+=num[ss][j][k];
                    }
                }
            }
        int ans=-1,m=(1<<n)-1;
        long long res=0;
        for(i=1;i<=n;i++)
        for(j=1;j<=n;j++){
            if(dp[m][i][j]>ans&&e[i][j]&&i!=j){
                ans=dp[m][i][j];
                res=num[m][i][j];
            }
            else if(dp[m][i][j]==ans&&e[i][j]&&i!=j)
                res+=num[m][i][j];
        }
        if(ans==-1)     printf("0 0\n");
        else            printf("%d %lld\n",ans,res/2);
    }
    return 0;
}

区间DP

H - Brackets POJ2955

Description

We give the following inductive definition of a “regular brackets” sequence:

the empty sequence is a regular brackets sequence,
if s is a regular brackets sequence, then (s) and [s] are regular brackets sequences, and
if a and b are regular brackets sequences, then ab is a regular brackets sequence.
no other sequence is a regular brackets sequence
For instance, all of the following character sequences are regular brackets sequences:

(), [], (()), ()[], ()[()]
while the following character sequences are not:

(, ], )(, ([)], ([(]
Given a brackets sequence of characters a1a2 … an, your goal is to find the length of the longest regular brackets sequence that is a subsequence of s. That is, you wish to find the largest m such that for indices i1, i2, …, im where 1 ≤ i1 < i2 < … < im ≤ n, ai1ai2 … aim is a regular brackets sequence.Given the initial sequence ([([]])], the longest regular brackets subsequence is [([])].

Input

The input test file will contain multiple test cases. Each input test case consists of a single line containing only the characters (, ), [, and ]; each input test will have length between 1 and 100, inclusive. The end-of-file is marked by a line containing the word “end” and should not be processed.

Output

For each input case, the program should print the length of the longest possible regular brackets subsequence on a single line.

Sample Input

((()))
()()()
([]])
)[)(
([][][)
end
Sample Output
6
6
4
0
6

dp[i][j]表示在区间i-j的最大括号序列数
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
int ma(int a,int b){return a>b?a:b;}
int mi(int a,int b){return a<b?a:b;}
char s[111];
int dp[111][111];
int main(){
    while(scanf("%s",s)!=EOF&&s[0]!='e'){
        int n=strlen(s);
        memset(dp,0,sizeof(dp));
        for(int len=2;len<=n;len++){
            for(int i=0,j=i+len-1;i<=n-len;i++,j++){
                if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']')){
                    dp[i][j]=dp[i+1][j-1]+2;
                }
                for(int k=i;k<j;k++)
                    dp[i][j]=ma(dp[i][k]+dp[k+1][j],dp[i][j]);
                //printf("%d  %d %d\n",i,j,dp[i][j]);
            }
        }
        printf("%d\n",dp[0][n-1]);
    }
    return 0;
}

I - Multiplication Puzzle POJ1651 MathJax to parse formulas

Description

The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move player takes one card out of the row and scores the number of points equal to the product of the number on the card taken and the numbers on the cards on the left and on the right of it. It is not allowed to take out the first and the last card in the row. After the final move, only two cards are left in the row.

The goal is to take cards in such order as to minimize the total number of scored points.

For example, if cards in the row contain numbers 10 1 50 20 5, player might take a card with 1, then 20 and 50, scoring

10150 + 50205 + 10505 = 500+5000+2500 = 8000

If he would take the cards in the opposite order, i.e. 50, then 20, then 1, the score would be

15020 + 1205 + 1015 = 1000+100+50 = 1150.

Input

The first line of the input contains the number of cards N (3 <= N <= 100). The second line contains N integers in the range from 1 to 100, separated by spaces.

Output

Output must contain a single integer - the minimal score.

Sample Input

6
10 1 50 50 20 5

Sample Output

3650

dp[i][j]表示把i、i+1……j-1取走的区间最小值
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
int ma(int a,int b){return a>b?a:b;}
int mi(int a,int b){return a<b?a:b;}
int dp[111][111],a[111],n;
int main(){
    while(scanf("%d",&n)!=EOF){
        for(int i=1;i<=n;i++)   scanf("%d",&a[i]);
        memset(dp,0,sizeof(dp));
        for(int len=2;len<n;len++){
            for(int i=2;i<=n-len+1;i++){
                int j=i+len-1;
                dp[i][j]=inf;
                for(int k=i;k<j;k++)//最后取第k个值得分
                    dp[i][j]=mi(dp[i][j],dp[i][k]+dp[k+1][j]+a[i-1]*a[k]*a[j]);
                //printf("%d %d %d\n",i,j,dp[i][j]);
            }
        }
        printf("%d\n",dp[2][n]);
    }
    return 0;
}

J - Halloween Costumes LightOJ1422

Description

Gappu has a very busy weekend ahead of him. Because, next weekend is Halloween, and he is planning to attend as many parties as he can. Since it’s Halloween, these parties are all costume parties, Gappu always selects his costumes in such a way that it blends with his friends, that is, when he is attending the party, arranged by his comic-book-fan friends, he will go with the costume of Superman, but when the party is arranged contest-buddies, he would go with the costume of ‘Chinese Postman’.
Since he is going to attend a number of parties on the Halloween night, and wear costumes accordingly, he will be changing his costumes a number of times. So, to make things a little easier, he may put on costumes one over another (that is he may wear the uniform for the postman, over the superman costume). Before each party he can take off some of the costumes, or wear a new one. That is, if he is wearing the Postman uniform over the Superman costume, and wants to go to a party in Superman costume, he can take off the Postman uniform, or he can wear a new Superman uniform. But, keep in mind that, Gappu doesn’t like to wear dresses without cleaning them first, so, after taking off the Postman uniform, he cannot use that again in the Halloween night, if he needs the Postman costume again, he will have to use a new one. He can take off any number of costumes, and if he takes off k of the costumes, that will be the last k ones (e.g. if he wears costume A before costume B, to take off A, first he has to remove B).
Given the parties and the costumes, find the minimum number of costumes Gappu will need in the Halloween night.
Input
Input starts with an integer T (≤ 200), denoting the number of test cases.
Each case starts with a line containing an integer N(1 ≤ N ≤ 100) denoting the number of parties. Next line contains N integers, where the ith integer ci(1 ≤ ci ≤ 100) denotes the costume he will be wearing in party i. He will attend party 1 first, then party 2, and so on.
Output
For each case, print the case number and the minimum number of required costumes.
Sample Input
2
4
1 2 1 2
7
1 2 1 1 3 2 1
Sample Output
Case 1: 3
Case 2: 4

dp[i][j]表示在第i天和第j天要穿的最小服装数
如果第j天选择穿新衣服,那么dp[i][j]=dp[i][j-1]+1;
选择脱的话就去找一个第k天的衣服和j天相同,dp[i][j]=dp[i][k]+dp[k+1][j-1]
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
int ma(int a,int b){return a>b?a:b;}
int mi(int a,int b){return a<b?a:b;}
int t,dp[111][111],a[111],n;
int main(){
    int cas=1;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)   scanf("%d",&a[i]);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)   dp[i][i]=1;
        for(int len=2;len<=n;len++){
            for(int i=1;i<=n-len+1;i++){
                int j=i+len-1;
                dp[i][j]=dp[i][j-1]+1;//穿上
                for(int k=j-1;k>=i;k--)
                    if(a[k]==a[j])
                        dp[i][j]=mi(dp[i][j],dp[i][k]+dp[k+1][j-1]);
            }
        }
        printf("Case %d: %d\n",cas++,dp[1][n]);
    }
    return 0;
}

K - String painter MathJax to parse formulas HDU2476

Description
There are two strings A and B with equal length. Both strings are made up of lower case letters. Now you have a powerful string painter. With the help of the painter, you can change a segment of characters of a string to any other character you want. That is, after using the painter, the segment is made up of only one kind of character. Now your task is to change A to B using string painter. What’s the minimum number of operations?

Input

Input contains multiple cases. Each case consists of two lines:

The first line contains string A.

The second line contains string B.

The length of both strings will not be greater than 100.

Output

A single line contains one integer representing the answer.

Sample Input 

zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd

Sample Output 

6
7
dp[i][j]表示将对应位置为【i,j】的空白串刷成B串的最小次数,ans【i】表示将A串前i个刷成B串的最小次数
///先对dp[i][j]进行处理,首先dp[i][j]=dp[i+1][j]+1,
///如果区间内有一个k和i字符相同,dp[i][j]=ma(dp[i][j],dp[i+1][k]+dp[k+1][j])
///ans[i]类似处理即可
#i

nclude<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
int ma(int a,int b){return a>b?a:b;}
int mi(int a,int b){return a<b?a:b;}
char s[111],ss[111];
int dp[111][111],ans[111];
int main(){
    while(scanf("%s%s",s,ss)!=EOF){
        int n=strlen(s);
        memset(dp,0,sizeof(dp));
        for(int len=1;len<=n;len++){
            for(int i=0;i<=n-len;i++){
                int j=i+len-1;
                dp[i][j]=dp[i+1][j]+1;
                for(int k=i+1;k<=j;k++)
                if(ss[i]==ss[k])
                    dp[i][j]=mi(dp[i][j],dp[i+1][k]+dp[k+1][j]);
            }
        }
        memset(ans,0,sizeof(ans));
        for(int i=0;i<n;i++)    ans[i]=dp[0][i];
        for(int i=0;i<n;i++){
            if(s[i]==ss[i])     ans[i]=ans[i-1];
            else{
                for(int j=0;j<i;j++)
                    ans[i]=mi(ans[i],ans[j]+dp[j+1][i]);
            }
        }
        printf("%d\n",ans[n-1]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值