信息学奥赛一本通 5.2 树形动态规划

题解在代码中

二叉苹果树[loj 10153]

/*
若要留q条边便是要留q+1个点
所以记忆化搜索
dp[pos][ans]=max(dp[pos][ans],dp[l[pos]][k]+dp[r[pos]][ans-k-1]+a[pos])
0<=k<=ans-1
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int f=1,ans=0;char c;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();}
    return ans*f;
}
int n,q;
int book[101][101],a[101],l[101],r[101];
void dfs(int pos){
    for(int i=1;i<=n;i++)
    {
        if(book[pos][i]!=-1)
        {
            a[i]=book[pos][i];
            book[pos][i]=-1;book[i][pos]=-1;
            l[pos]=i;
            dfs(i);
            break;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(book[pos][i]!=-1)
        {
            a[i]=book[pos][i];
            book[pos][i]=-1;book[i][pos]=-1;
            r[pos]=i;
            dfs(i);
            break;
        }
    }
    return;
}
int dp[101][101];
int solve(int pos,int ans)
{
    if(ans==0) return 0;
    if(dp[pos][ans]!=-1) return dp[pos][ans];
    if(r[pos]==0&&l[pos]==0) return a[pos];
    for(int j=0;j<=ans-1;j++)
        dp[pos][ans]=max(dp[pos][ans],solve(l[pos],j)+solve(r[pos],ans-1-j)+a[pos]);
    return dp[pos][ans];

}
int main()
{
    memset(dp,-1,sizeof(dp));
    memset(book,-1,sizeof(book));
    n=read(),q=read();
    for(int i=1;i<n;i++)
    {
        int u=read(),v=read(),w=read();book[u][v]=w;book[v][u]=w;
    }
    dfs(1);
    cout<<solve(1,q+1);
}

选课[loj 10154]

/*
建立一个虚根0使得将森林转化成为树
dp[i][j]表示为以i为根的子树下最多选j门课的最大学分
dfs后先进行背包处理
这是先不考虑先修课
再将有先修课 (pos!=0)时dp的容积为容积-1的最大值加上选修此门课的积分
dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[son][k])
j (m~0)
    k(j~0)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int f=1,ans=0;char c;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();}
    return ans*f;
}
int n,m;
struct node{
    int u,v,nex;
}x[1001];
int s[1001];
int t,cnt;
int dp[1001][1001],head[1001];
void add(int u,int v)
{
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
void dfs(int pos)
{
    for(int p=head[pos];p!=-1;p=x[p].nex)
    {
        int xx=x[p].v;
        dfs(xx);
        for(int i=m;i>=0;i--)
            for(int j=i;j>=0;j--) dp[pos][i]=max(dp[pos][i],dp[pos][i-j]+dp[xx][j]);
    }
    if(pos!=0)
    {
        for(int i=m;i>=1;i--)  dp[pos][i]=dp[pos][i-1]+s[pos];
    }

//    for(int i=m;i>=0;i--) cout<<"位置:"<<pos<<"  选课:"<<i<<"  dp:"<<dp[pos][i]<<endl;
//    system("pause");
    return ;
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read(),m=read();
    for(int i=1;i<=n;i++)
    {
        t=read(),s[i]=read();
        add(t,i);
    }
    dfs(0);
    cout<<dp[0][m];
}

数字转换[loj 10155]

/*
先预处理好因数和,再建一棵树
求树的最长链即可
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#pragma GCC optimize(2)
using namespace std;
inline long long read()
{
    long long f=1,ans=0;char c;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();}
    return ans*f;
}
long long n,cnt;
struct node{
    long long u,v,nex;
}x[100001];
long long head[100001];
long long dp1[100001],dp2[100001];
void add(long long u,long long v)
{
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
long long sum[100001];
long long maxn,book[100001];
//dp1表示最长,dp2表次长
void dfs(long long pos)
{
//    cout<<pos<<endl;
    for(long long i=head[pos];i!=-1;i=x[i].nex)
    {
        long long p=x[i].v;
        if(book[p]==0)
        {
            book[p]=1;
            dfs(p);
            if(dp1[p]+1>dp1[pos]) dp2[pos]=dp1[pos],dp1[pos]=dp1[p]+1;
            else if(dp1[p]+1>dp2[pos]) dp2[pos]=dp1[p]+1;
            maxn=max(maxn,dp1[pos]+dp2[pos]);
        }
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read();
    for(int i=1;i<=n/2;i++)
    {
        for(int j=i*2;j<=n;j+=i)
        {
            sum[j]+=i;
        }
    }
    for(int i=2;i<=n;i++)
        if(sum[i]<i) add(sum[i],i),add(i,sum[i]);
    book[1]=1;
    dfs(1);
    cout<<maxn;
}

战略游戏[loj 10156]

/*
0为不选,1为选
pos的子孙为x
dp[pos][0]=sum(dp[x][1])
dp[pos][1]=sum(min(dp[x][0],dp[x][1]));
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int f=1,ans=0;char c;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();}
    return ans*f;
}
struct node{
    int u,v,nex;
}x[100001];
int head[1501],n,cnt,dp[1501][3],book[1501];
void add(int u,int v)
{
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
void dfs(int pos)
{
//    cout<<pos<<endl;
    dp[pos][1]=1;
    for(int i=head[pos];i!=-1;i=x[i].nex)
    {
        int p=x[i].v;
        if(book[p]==0)
        {
            book[p]=1;
            dfs(p);
            dp[pos][0]+=dp[p][1];
            dp[pos][1]+=min(dp[p][0],dp[p][1]);
//            cout<<pos<<" "<<dp[pos][0]<<" "<<dp[pos][1]<<" "<<endl;
        }
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read();
    for(int i=1;i<=n;i++)
    {
        int t=read(),k=read();
        for(int j=1;j<=k;j++)
        {
            int p=read();
            add(t,p),add(p,t);
        }
    }
    book[0]=1;
    dfs(0);
    cout<<min(dp[0][0],dp[0][1]);
}

皇宫看守[loj 10157]

/*
dp[pos][0]为pos自己安放
dp[pos][1]为pos被自己的父亲看到
dp[pos][2]为pos被自己的子孙看到

dp[pos][0]+=min(dp[x][0],dp[x][1],dp[x][2])
dp[pos][1]+=min(dp[x][0],dp[x][2])
dp[pos][2]+=min(dp[x][0],dp[x][2])
dp[pos][2]+=k,dp[pos][0]+=s[pos]
k=min(k,dp[pos][0]-min(dp[pos][0],dp[pos][2]));
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int f=1,ans=0;char c;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();}
    return ans*f;
}
int dp[1501][3];
struct node{
    int u,v,nex;
}x[2250001];
int s[1501];
int a[1501],cnt,n;
int head[1501];
void add(int u,int v)
{
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int dfs(int pos,int fath)
{
    int k=99999999;
    for(int i=head[pos];i!=-1;i=x[i].nex)
    {
        int p=x[i].v;
        if(p==fath) continue;
        dfs(p,pos);
        dp[pos][0]+=min(min(dp[p][0],dp[p][1]),dp[p][2]);
        dp[pos][1]+=min(dp[p][0],dp[p][2]);
        dp[pos][2]+=min(dp[p][0],dp[p][2]);
        k=min(k,dp[p][0]-min(dp[p][0],dp[p][2]));
    }
    dp[pos][0]+=s[pos];
    dp[pos][2]+=k;
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read();
    for(int i=1;i<=n;i++)
    {
        int xx=read();
        s[xx]=read();
        int m=read();
        for(int j=1;j<=m;j++)
        {
            int p=read();
//            cout<<xx<<" "<<p<<endl;
            add(xx,p);
            add(p,xx);
        }
    }
    dfs(1,0);
    cout<<min(dp[1][0],dp[1][2]);
}

加分二叉树[loj 10158]

/*
中序遍历
左子树——根——右子树
每次枚举根
进行记忆化dfs
将last存放最优根
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int f=1,ans=0;char c;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();}
    return ans*f;
}
int dp[31][31],s[31],n,last[31][31];
int dfs(int l,int r)
{
//    cout<<l<<" "<<r<<endl;
    if(l==r) return s[l];
    if(l>r) return 1;
    if(dp[l][r]!=-1) return dp[l][r];
    for(int i=l;i<=r;i++)
    {
        int p=dfs(l,i-1)*dfs(i+1,r)+s[i];
        if(p>dp[l][r])
        {
            dp[l][r]=p;
            last[l][r]=i;
        }
    }
    return dp[l][r];
}
void sc(int l,int r)
{

    if(l>r) return;
    if(l==r)
    {
        cout<<l<<" ";
        return;
    }
    cout<<last[l][r]<<" ";
    sc(l,last[l][r]-1);
    sc(last[l][r]+1,r);
    return;
}
int main()
{
    memset(dp,-1,sizeof(dp));
    n=read();
    for(int i=1;i<=n;i++) s[i]=read();
    cout<<dfs(1,n)<<endl;
//    cout<<
    sc(1,n);
}

旅游规划[loj 10159]

/*
此题是找最长链上的所有店
dp1求子树上最长路径
dp2求子树上次长路径

两者相加便可以求出最长路径的长度

dp3记录除子树外的最长路径

*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int f=1,ans=0;char c;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();}
    return ans*f;
}
struct node{
    int u,v,nex;
}x[400001];
int n,cnt,head[200001];
int book[200001],dp3[200001],maxn,dp1[200001],dp2[200001];
void add(int u,int v)
{
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
void dfs(int pos)
{
//    cout<<pos<<endl;
    for(int i=head[pos];i!=-1;i=x[i].nex)
    {
        int p=x[i].v;
//        cout<<p<<endl;
        if(book[p]==0)
        {
            book[p]=1;
            dfs(p);
            if(dp1[p]+1>=dp1[pos])
            {
                dp2[pos]=dp1[pos];
                dp1[pos]=dp1[p]+1;
            }
            else if(dp1[p]+1>=dp2[pos])
                dp2[pos]=dp1[p]+1;
            maxn=max(maxn,dp1[pos]+dp2[pos]);
        }
    }
    return;
}
void dfs1(int pos,int fath)
{
    int sum=0;
    for(int i=head[pos];i!=-1;i=x[i].nex)
        if(x[i].v!=fath&&dp1[pos]==dp1[x[i].v]+1) sum++;
    for(int i=head[pos];i!=-1;i=x[i].nex)
    {
        if(x[i].v!=fath)
        {
            if(dp1[x[i].v]+1!=dp1[pos]) dp3[x[i].v]=max(dp1[pos],dp3[pos])+1;
            else if(dp1[x[i].v]+1==dp1[pos]&&sum>1)dp3[x[i].v]=max(dp1[pos],dp3[pos])+1;
            else dp3[x[i].v]=max(dp2[pos],dp3[pos])+1;
            dfs1(x[i].v,pos);
        }
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read();
//    for(int i=0;i<n;i++) f[i]=i;
    for(int i=1;i<n;i++)
    {
        int u=read(),v=read();
        add(u,v),add(v,u);
    }
    book[0]=1;
    dfs(0);
//    cout<<maxn<<" ";
    memset(book,0,sizeof(book));
    dfs1(0,-10);
    for(int i=0;i<n;i++)
        if(dp1[i]+max(dp2[i],dp3[i])==maxn) cout<<i<<endl;
    return 0;
}

周年纪念晚会[loj 10160]

/*
0不选1选
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int f=1,ans=0;char c;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();}
    return ans*f;
}
int a[6001],n;
struct node{
    int u,v,nex;
}x[6001];
int cnt;
int head[6001],dp[6001][3],t[6001];
void add(int u,int v)
{
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
void dfs(int pos)
{
//    cout<<pos<<endl;
    dp[pos][0]=0;
    dp[pos][1]=a[pos];
    for(int i=head[pos];i!=-1;i=x[i].nex)
    {
        int p=x[i].v;
        dfs(p);
        dp[pos][0]+=max(0,max(dp[p][0],dp[p][1]));
        dp[pos][1]+=max(0,dp[p][0]);

    }
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read();
    memset(dp,0xcf,sizeof(dp));
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<n;i++)
    {
        int u=read(),v=read();
        add(v,u);t[u]=1;
    }
    int sry=1;
    while(t[sry]==1) sry++;
    dfs(sry);
    cout<<max(dp[sry][0],dp[sry][1]);
}

叶子的颜色[loj 10161]

/*
dp[pos][0]表示pos涂黑色
1 表示涂白色
2 表示不涂

dp[pos][0]+=min(dp[x][0]-1,dp[x][1],dp[x][2])
1,2同理

-1是因为此点就不需要涂 

预处理见代码
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int f=1,ans=0;char c;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();}
    return f*ans;
}
int m,n,c[6001];
struct node{
    int u,v,nex;
}x[20001];
int head[10001],cnt;
void add(int u,int v)
{
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int book[10001],dp[10001][3];
void dfs(int pos)
{
    if(pos>=1&&pos<=m)
    {
        dp[pos][c[pos]]=1;
        dp[pos][1-c[pos]]=dp[pos][2]=2<<30-1;
    }
    else{
        dp[pos][1]=dp[pos][0]=1;
    }
    for(int i=head[pos];i!=-1;i=x[i].nex)
    {
        int t=x[i].v;
        if(book[t]==0)
        {
            book[t]=1;
            dfs(t);
            dp[pos][0]+=min(dp[t][0]-1,min(dp[t][1],dp[t][2]));
            dp[pos][1]+=min(dp[t][1]-1,min(dp[t][0],dp[t][2]));
            dp[pos][2]+=min(dp[t][0],min(dp[t][1],dp[t][2]));
        }
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read(),m=read();
    for(int i=1;i<=m;i++) c[i]=read();
    for(int i=1;i<n;i++)
    {
        int u=read(),v=read();
        add(u,v),add(v,u);
    }
    book[n]=1;
    dfs(n);
    cout<<min(dp[n][0],min(dp[n][1],dp[n][2]));
}

骑士[loj 10162]

/*
断环为链,与没有上司的舞会接下来的十分相似
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline long long read()
{
    long long f=1,ans=0;char c;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();}
    return f*ans;
}
struct node{
    long long u,v,nex;
}x[2000001];
long long cnt;
long long head[1000001],n,s[1000001],vis[1000001],root,book[1000001],uu,vv;
void add(long long u,long long v)
{
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}

bool flag;
long long ans;
void dfs(long long pos,long long fa)
{
    for(long long i=head[pos];i!=-1;i=x[i].nex)
    {
        long long p=x[i].v;
        if(fa!=p)
        {
            if(vis[p]==0)
            {
                vis[p]=1;
                dfs(p,pos);
            }
            else{
                flag=true;
                uu=pos,vv=p;
            }
        }
    }
}
long long dp[1000001][2];//0没用,1用
long long inf=2<<30-1;
void dfs_dp(long long pos,long long fa)
{
//    cout<<pos<<endl;
    dp[pos][1]=s[pos];
    for(long long i=head[pos];i!=-1;i=x[i].nex)
    {
        long long p=x[i].v;
        if(p!=fa)
        {
            if(p==-inf) continue;
            dfs_dp(p,pos);
            dp[pos][0]+=max(dp[p][0],dp[p][1]);
            dp[pos][1]+=dp[p][0];
        }
    }
    return;
}
void work(long long pos)
{
    memset(dp,0,sizeof(dp));
    flag=false;
    vis[pos]=1;
    dfs(pos,-1);
//    cout<<uu<<" "<<vv<<endl;
    if(flag==false)
    {
        dfs_dp(pos,-1);
        ans+=max(dp[pos][0],dp[pos][1]);
    }
    else if(flag==true)
    {
        long long maxn=0;
        for(long long i=head[uu];i!=-1;i=x[i].nex)
        {
            long long p=x[i].v;
            if(p==vv)
            {
                x[i].v=-inf;
                break;
            }
        }
        for(long long i=head[vv];i!=-1;i=x[i].nex)
        {
            long long p=x[i].v;
            if(p==uu)
            {
                x[i].v=-inf;
                break;
            }
        }
//        cout<<uu<<" "<<vv<<endl;
        dfs_dp(uu,-1);
//        return ;
        long long x1=dp[uu][0];
//        cout<<x1<<endl;
        memset(dp,0,sizeof(dp));
        dfs_dp(vv,-1);
        long long x2=dp[vv][0];
//        cout<<x2<<endl;
        maxn=max(x1,x2);
        ans+=maxn;
    }
}
int main(void)
{
    memset(head,-1,sizeof(head));
    n=read();
    for(long long i=1;i<=n;i++)
    {
        s[i]=read();
        long long p=read();
        add(i,p),add(p,i);
    }
    for(long long i=1;i<=n;i++)
    {
        if(vis[i]==0)
        {
            work(i);
//            return 0;
        }
    }
    cout<<ans;
}

原文地址:https://www.cnblogs.com/si-rui-yang/p/9502543.html

时间: 2024-08-30 15:14:01

信息学奥赛一本通 5.2 树形动态规划的相关文章

信息学奥赛一本通 5.4 状态压缩动态规划

#loj 10170. 「一本通 5.4 例 1」骑士 看数据范围n<=10,所以不是搜索就是状压dp,又因为搜索会超时所以用dp dp[i][k][j]表示现已经放到第i行,前面共有k个,这一行状态为j so,dp[i][k][j]=dp[i-1][k-num[j]][t] #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cma

信息学奥赛一本通 5.1 区间类动态规划

石子合并[loj 10147] /* dp[i][j]=max or min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]) i<=k<j */ #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; inline int re

【信息学奥赛一本通】第三部分_栈 ex1_4cale (中缀转后缀7符号)

其实这个中缀转后缀是费了很大功夫的,明白算法后第一次实现花了近三小时ORZ #include <stdio.h> #include <string.h> #include <ctype.h> char Mstr[511],Msta[511] = {'@'},Bstr[511]; int sta[511]; const short list[4][4] = {{0,-1,1,1},{1,0,1,1},{1,1,1,-2},{-1,-1,2,1}}; int level (

【信息学奥赛一本通】第三部分_队列 ex2_3produce 产生数

给出一个整数n(n<=2000)(代码可适用n<=10^31)和k个变换规则(k<=15). 规则:1.1个数字可以变换成另1个数字: 2.规则中右边的数字不能为零. BFS 1 #include <stdio.h> 2 #include <string.h> 3 #define maxn 1000 4 5 char num[33]; 6 int len,q[maxn],Visited[11]; 7 long long ans = 1; 8 9 int main

信息学奥赛一本通 提高篇 序列第k个数 及 快速幂

我是传送门 这个题首先是先判断是等差还是等比数列 等差的话非常简单: 前后两个数是等差的,举个栗子: 3 6 9 12 这几个数,(我感觉 1 2 3 4并说明不了什么) 每次都加3嘛,很容易看出,第一个数是3 * 1,第二个是3 * 2....以此类推 第k个数 = (第2个数 - 第1个数) * k ; (z - y) * k % 200907 % 200907 的原因是题目要求 但是这样并不能过 hack一下 4 7 10 13 用原先的公式:(7 - 4) * 4 % 200907 =

【信息学奥赛一本通 提高组】第二章 二分与三分

一.二分 二分法,在一个单调有序的集合或函数中查找一个解,每次分为左右两部分,判断解在那个部分并调整上下界,直到找到目标元素,每次二分都将舍弃一般的查找空间,因此效率很高. 二分常见模型 1.二分答案 最小值最大(或是最大值最小)问题,这类双最值问题常常选用二分法求解,也就是确定答案后,配合贪心,DP等其他算法检验这个答案是否合理,将最优化问题转化为判定性问题.例如,将长度为n的序列ai分为最多m个连续段,求所有分法中每段和的最大值的最小是多少? 2.二分查找 用具有单调性的布尔表达式求解分界点

求后序遍历(信息学奥赛一本通 1339)

假设有棵树,长下面这个样子,它的前序遍历,中序遍历,后续遍历都很容易知道. PreOrder: GDAFEMHZ InOrder: ADEFGHMZ PostOrder: AEFDHZMG 现在,假设仅仅知道前序和中序遍历,如何求后序遍历呢?比如,已知一棵树的前序遍历是"GDAFEMHZ",而中序遍历是"ADEFGHMZ"应该如何求后续遍历? 第一步,root最简单,前序遍历的第一节点G就是root. 第二步,继续观察前序遍历GDAFEMHZ,除了知道G是root,

最大子矩阵(信息学奥赛一本通 1224)

[题目描述] 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1×1)子矩阵. [输入] 输入是一个N×N的矩阵.输入的第一行给出N(0<N≤100).再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行).已知矩阵中整数的范围都在[−127,127]. [输出] 输出最大子矩阵的大小. [输入样例] 4 0 -2 -7 0 9 2 -6 2 -4 1

樱花(信息学奥赛一本通 1624)

[题目描述] 原题来自:HackerRank Equations 求不定方程: 1/x + 1/y = 1/n! 的正整数解 (x,y)的数目. [输入] 一个整数 n. [输出] 一个整数,表示有多少对 (x,y) 满足题意.答案对 109+7 取模. [输入样例] 2 [输出样例] 3 [提示] 样例说明 共有三个数对 (x,y) 满足条件,分别是 (3,6),(4,4) 和 (6,3). 数据范围与提示: 对于 30% 的数据,n≤100: 对于全部数据,1≤n≤106 . (这里不得不吐