EC final 康复—DP练习

HDU4055

给一个I、D、?组成的字符串长度为n,那么有n+1个数字,数字要求满足对有I,数字递增。有D,数字递减,有?,数字随意

比如131就满足ID,ID的所有数字有132,231.给一个字符串问有多少种方案。

这里假设一个dp[i][j]表示长度为i的字符串,结尾数字是j有dp[i][j]种方法。

这里有个大前提,就是结尾为j的时候,把所有大于j的数字+1,就可以得到之前无j的所有排列,且满足题意

那么转移可以这样想,对于‘I’,dp[i][j]=dp[i-1][1~j-1]进行累加,表示由之前的低位转移过来,表示之前没有j这个数字,把所有数字+1,就仍然可以满足题目所给条件。

对于'D',dp[i][j]=dp[i-1][j~i]就仍然相当把所有大于j的数字+1,j还要就是因为其在新的转移中变成了j+1

对于?,就是D+I的结果。

wa:有'取模'与‘-’的运算,必须+mod,因为有可能大的数字mod后变小了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1007;
const ll mod=1e9+7;
ll dp[maxn][maxn];
ll dp2[maxn][maxn];
char s1[maxn];
int main(){
    ll i,j,k,f1,f2,f3,f4,t1,t2,t3,t4,n,m;
    ll Max;
    ll T;
    freopen("in.txt","r",stdin);
    while(scanf("%s",s1+1)==1){
        ll len1=strlen(s1+1); //注意这里为 是s1+1
        memset(dp,0,sizeof(dp));
        memset(dp2,0,sizeof(dp2));
        dp[1][1]=1;
        dp2[1][1]=1;
        for(i=2;i<=len1+1;i++){
                for(j=1;j<=i;j++){
                    if(s1[i-1]=='I'){ //增加,j,(1-j)
                        dp[i][j]=dp2[i-1][j-1];
                    }else if(s1[i-1]=='D'){
                        dp[i][j]=(mod+dp2[i-1][i-1]-dp2[i-1][j-1])%mod;
                    }else{
                        dp[i][j]=dp2[i-1][i-1];
                    }
                }
                for(j=1;j<=i;j++)
                    dp2[i][j]=(dp2[i][j-1]+dp[i][j])%mod;
        }
        ll res=0;
        for(i=1;i<=len1+1;i++)
        res=(res+dp[len1+1][i])%mod;
        printf("%lld\n",res);
    }
    return 0;
}

hdu2196:

题意:范围1e4, 给一棵树,求出每个结点能到的最远距离。

考虑每个结点的最远点距离多少,一个结点的最远距离要么是其子节点/要么是其父亲结点连接的最远结点(第二远结点,因为最远可能是连接的这个结点,然后每个点判断其最远和次远(第一个如果是父节点,那么最远的2个就按排序后的第二与第三。

重点在于到子结点以后,父节点与其的距离不知道,此时dfs传下来,需要每次都传父节点到子节点的距离.如果选择是父节点的点且不是自己,那么需要加上自己到父节点的距离。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e5+8;
const ll mod=1e9+7;
ll q1[maxn];
struct ttt{
    ll num,key;
};
ttt dp[10005][2];//0表示最小,1表示c次小
ttt res[10005][2];
vector<ttt>qq[10050];
ll dfs(ll x,ll fa){
    if(qq[x].size()==1&&fa!=-1){
        ;
    }else{
        ll i,u,len;
        ll t1,t2,num1,num2;
        t1=t2=0;
        num1=num2=-1;
        for(i=0;i<qq[x].size();i++){
            u=qq[x][i].num;
            len=qq[x][i].key;
            if(u==fa)continue;
            dfs(u,x);
            if(t1==0){
                t1=dp[u][0].key+len;
                num1=u;
                continue;
            }
            if(dp[u][0].key+len>=t2){
                t2=dp[u][0].key+len;
                num2=u;
            }
            if(t2>t1){
                swap(t2,t1);
                swap(num2,num1);
            }
        }
        dp[x][0].num=num1;dp[x][0].key=t1;
        dp[x][1].num=num2;dp[x][1].key=t2;
    }
}
ll cmp(ttt x,ttt y){
    return x.key>y.key;

}


ttt max1[4];
ll dfs2(ll x,ll fa,ll len){
    ll i,u;
    max1[2]=res[fa][0];max1[3]=res[fa][1];
    if(fa==-1){
            res[x][0]=dp[x][0];
            res[x][1]=dp[x][1];
    }else{
            max1[0]=dp[x][0];
            max1[1]=dp[x][1];

            if(max1[2].num!=x){
                max1[2].key+=len;
            }
            if(max1[3].num!=x){
                max1[3].key+=len;
            }

            sort(max1,max1+4,cmp);
            if(max1[0].num==x){ //最小与次小均是
                res[x][0]=max1[1];
                res[x][1]=max1[2];
            }else{
                res[x][0]=max1[0];
                if(max1[1].num==x){
                    res[x][1]=max1[2];
                }else{
                    res[x][1]=max1[1];
                }
            }

    }
    for(i=0;i<qq[x].size();i++){
        u=qq[x][i].num;
        if(u==fa)continue;
        dfs2(u,x,qq[x][i].key);
    }
}
int main(){
    ll i,j,k,f1,f2,f3,f4,t1,t2,t3,t4,n,m;
    //freopen("in.txt","r",stdin);
    while(scanf("%lld",&n)==1){
    memset(res,0,sizeof(res));
    memset(dp,0,sizeof(dp));
    ttt u,v;
    for(i=1;i<=n;i++)
        qq[i].clear();

    for(i=2;i<=n;i++){
       scanf("%lld %lld",&t1,&t2);
       u.num=t1;u.key=t2;
       qq[i].push_back(u);
       u.num=i;
       qq[t1].push_back(u);
    }
    dfs(1,-1);
    dfs2(1,-1,0);
    for(i=1;i<=n;i++)
        printf("%lld\n",res[i][0].key);

    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值