2016-08-22做题总结

显然,今天(好吧已经算是昨天了)的一天还算是有点意义的。
首先,不晓得应该是感谢还是鄙视军训的时候肚子疼的我~真的不是故意的。。。。
这两天主要搞的是树形DP和状态压缩DP。不过, LG又打算喊 我 和 猪鱼 做一些无聊的搜索题。。。
好吧,还是按顺序说::::::::(冒号是毫无意义的)
第一题,NOIP的加分二叉树

    #include<bits/stdc++.h>
    using namespace std;
    int dp[30][30],a[30],rt[30][30];
    int score(int l,int r){
    if(dp[l][r])return dp[l][r];
    if(l>r)return dp[l][r]=1;
    if(l==r){rt[l][l]=l;return dp[l][l]=a[l];}
    int maxx=-1;
    for(int i=l;i<=r;i++){
        int s=score(l,i-1)*score(i+1,r)+a[i];
        if(s>maxx){
            maxx=s;rt[l][r]=i;
        }
    }
    return dp[l][r]=maxx;
    }
    void Pre(int l,int r){
        if(l>r)return;
        printf("%d ",rt[l][r]);
        Pre(l,rt[l][r]-1);
        Pre(rt[l][r]+1,r);
    }
    int main(){
        int i,j,k,m,n;
        scanf("%d",&n);
        for(i=1;i<=n;i++)scanf("%d",a+i);
        int ans=score(1,n);
        printf("%d\n",ans);
        Pre(1,n);
        return 0;
    }

没什么,显然是一道很右脑的题目,没什么多说的。
第二道POJ2486 Apple Tree

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
using namespace std;
vector <int> old[210],now[210];
int dp[2][210][210],n,m,k,val[210];
bool p[210];
void updata(int x){
    p[x]=1;
    for(int i=0;i<old[x].size();i++){
        if(p[old[x][i]])continue;
        now[x].push_back(old[x][i]);
        updata(old[x][i]);
    }
}
void dfs(int x){
    for(int i=0;i<=k;i++)dp[0][x][i]=dp[1][x][i]=val[x];
    for(int i=0;i<now[x].size();i++){
        int y=now[x][i];
        dfs(y);
        for(int j=k;j>=0;j--){      
            for(int jj=0;jj<=j;jj++){
                dp[0][x][j+1]=max(dp[0][x][j+1],dp[1][x][jj]+dp[0][y][j-jj]);
                dp[0][x][j+2]=max(dp[0][x][j+2],dp[0][x][jj]+dp[1][y][j-jj]);
                dp[1][x][j+2]=max(dp[1][x][j+2],dp[1][x][jj]+dp[1][y][j-jj]);   
            }
        }
    }
}
int main(){
    int x,y,i,j;
    while(scanf("%d%d",&n,&k)!=EOF){
        memset(dp,0,sizeof(dp));
        memset(p,0,sizeof(p));
        for(i=0;i<210;i++){
            old[i].clear();
            now[i].clear();
        }
        for(i=1;i<=n;i++)scanf("%d",val+i);
        for(i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            old[x].push_back(y);
            old[y].push_back(x);
        }
        updata(1);
        dfs(1);
        printf("%d\n",dp[0][1][k]);
    }

    return 0;
}

哇啦啦那些该死的状态转移方程真是搞得我想死了!!
不过,幸好我还没死(—>机智的我)于是继续~
下一个是HUD2196 Computer

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#define ll long long
using namespace std;
const ll maxn=10010;
struct Edge{
    ll v,w;
};
ll f[maxn][2];
bool p[maxn];
vector <Edge> e[maxn];
ll dfs1(ll u){
    //printf("dfs : %lld\n",u);
    ll i;p[u]=1;
    for(i=0;i<e[u].size();i++){
        ll v=e[u][i].v;
        ll w=e[u][i].w;
        if(p[v])continue;
        ll tmp=dfs1(v)+w;
        //printf("f[%lld][0] : %lld  ||||   %lld\n",u,f[u][0],tmp);
        f[u][0]=max(f[u][0],tmp);
    }
    return f[u][0];
}

void dfs2(ll u){
    p[u]=1;
    ll i,max1=0,max2=0,v1,v2;
    for(i=0;i<e[u].size();i++){
        ll v=e[u][i].v;
        ll w=e[u][i].w;
        if(p[v])continue;
        ll tmp=w+f[v][0];
        if(tmp>max1){
            max2=max1;v2=v1;
            max1=tmp;v1=v;
        }else if(tmp==max1||tmp>max2){
            max2=tmp;v2=v;
        }
    }
    if(u!=1){
        ll tmp=f[u][1],v=-1;
        if(tmp>max1){
            max2=max1;v2=v1;
            max1=tmp;v1=v;
        }else if(tmp==max1||tmp>max2){
            max2=tmp;v2=v;
        }
    }
    for(i=0;i<e[u].size();i++){
        ll v=e[u][i].v;
        ll w=e[u][i].w;
        if(p[v])continue;
        f[v][1]=v==v1?max2+w:max1+w;
        dfs2(v);
    }

}
int main(){
    ll i,j,u,v,k,m,n;
    while(scanf("%lld",&n)!=EOF){
        for(i=0;i<=n+1;i++)e[i].clear();
        memset(f,0,sizeof(f));
        for(i=2;i<=n;i++){
            scanf("%lld%lld",&u,&v);
            e[i].push_back((Edge){u,v});
            e[u].push_back((Edge){i,v});
        }
        /*for(i=1;i<=n;i++)
            for(j=0;j<e[i].size();j++)
                printf("%lld -> %lld : %lld\n",i,e[i][j].v,e[i][j].w);
        */
        memset(p,0,sizeof(p));
        dfs1(1);
        //for(i=1;i<=n;i++)cout<<f[i][0]<<" ";puts("");
        memset(p,0,sizeof(p));
        dfs2(1);
        for(i=1;i<=n;i++)
            printf("%lld\n",max(f[i][0],f[i][1]));
    }
    return 0;
}

显然,从这些迷之注释就可以看出来本人莫名其妙的错到了多interesting的地步。。。。。于是,坚强的我又挺了过来。
下一个是POJ2342 Anniversary party

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn=6010;
int a[maxn][2],fa[maxn],n,m;
bool p[maxn];
void DP(int x){
    p[x]=1;
    for(int i=1;i<=n;i++){
        if(fa[i]==x&&!p[i]){
            DP(i);
            a[x][1]+=a[i][0];
            a[x][0]+=max(a[i][1],a[i][0]);
        }
    }
}
int main(){
    int x,y,i,j,k;
    while(scanf("%d",&n)!=EOF){
        memset(a,0,sizeof(a));
        memset(p,0,sizeof(p));
        memset(fa,0,sizeof(fa));
        for(i=1;i<=n;i++)scanf("%d",&a[i][1]);
        int rt=0;
        while(scanf("%d%d",&x,&y)&&(x||y)){
            fa[x]=y;
            rt=x==rt?y:rt;
        }
        while(fa[rt])rt=fa[rt];
        DP(rt);
        int ans=max(a[rt][1],a[rt][0]);
        printf("%d\n",ans);
    }
    return 0;
}

搞完这个东西就可以说找到一点树形DP的感觉了—–>于是我就走了;
其实不能怪我,是 无聊的LG 又送了我一下状态压缩的东西:)
于是,状态压缩第一枪,POJ3254 Corn Field

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<stack>
using namespace std;
const int maxn=13;
const int maxm=1<<13;
int st[maxm],map[maxm],dp[maxn][maxm];
bool Judge1(int x){return (x&(x<<1))?0:1;};
bool Judge2(int x,int y){return (map[x]&st[y])?0:1;};
void Clear(){
    memset(st,0,sizeof(st));
    memset(map,0,sizeof(map));
    memset(dp,0,sizeof(dp));
}
stack <bool> Stack;
void Out_put(int x){
    do{
        Stack.push(x&1);
        x>>=1;
    }while(x>0);
    while(!Stack.empty()){
        cout<<Stack.top();
        Stack.pop();
    }
    cout<<" ";
}
int main(){
    int i,j,k,m,n;
    while(scanf("%d%d",&n,&m)!=EOF){
        Clear();
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++){
                int x;
                scanf("%d",&x);
                if(x==0)map[i]+=1<<(j-1);
            }
        int top=0;
        for(i=0;i<(1<<m);i++)
            if(Judge1(i))
                st[++top]=i;
        for(i=1;i<=top;i++)
            if(Judge2(1,i))
                dp[1][i]=1;
        for(i=2;i<=n;i++)
            for(j=1;j<=top;j++){
                if(!Judge2(i,j))continue;
                for(k=1;k<=top;k++){
                    if(!Judge2(i-1,k))continue;
                    if(st[j]&st[k])continue;
                    dp[i][j]+=dp[i-1][k];
                }
            }
        int ans=0;
        for(i=1;i<=top;i++){
            ans+=dp[n][i];
            ans%=100000000;
        }
        printf("%d\n",ans);
    }
    return 0;
}

这道题目做起来还算顺风顺水,具体也没什么好讲的。但是该死的我的。。。。迷之数组都是[0][0][0]…….

下一个没多大区别,
POJ1185 炮兵阵地

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int map[105];
int stk[65], sum[65];
int dp[105][65][65],top;
int get(int x){
    int ans=0;
    while(x){
        ans+=x&1;
        x>>=1;
    }return ans;
}
bool judge(int x){
    if(x&(x<<1))return false;
    if(x&(x<<2))return false;
    return true;
}
void pre(int n){

}
int main(){
    int n, m, r, c, i, j, k;
    cin>>n>>m;getchar();
    for(i=0;i<n;i++,getchar()){
        for(j=0;j<m;j++){
            char c;
            cin>>c;
            if(c=='H')map[i]|=1<<j;
        }
    }
    int top=0;
    for(int i=0;i<(1<<m);i++)
        if(judge(i)){
            stk[top]=i;
            sum[top++]=get(i);
        }   
    for(i=0;i<top;i++){
        if(!(stk[i]&map[0]))
            dp[0][0][i]=sum[i];
    }
    for(i=1;i<n;i++){//line now
        for(j=0;j<top;j++){//the situation about this(i) line
            if(stk[j]&map[i])continue;
            for(k=0;k<top;k++){//the situation about i-1 line
                if(stk[k]&stk[j])continue;
                for(int tmp=0;tmp<top;tmp++){// the situation about i-2 line
                    if(stk[j]&stk[tmp])continue;
                    if(!dp[i-1][tmp][k])continue;
                    dp[i][k][j]=max(dp[i][k][j],dp[i-1][tmp][k]+sum[j]);
                }

            }
        }
    }
    int ans=0;
    for(i=0;i<top;i++)
        for(j=0;j<top;j++)
            ans=max(ans,dp[n-1][i][j]);
    cout<<ans<<endl;

    return 0;
}

然后,开始为猪鱼的到来做准备(虽然不晓得他会不会游过来){
加了个vjudge的比赛;
第一题=洛谷新手村的function=POJ1579;
第二道=POJ1088滑雪;
//显然是两道毫无意义的弱鸡题目,但是被坑了
}
POJ 1579

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define ll long long
using namespace std;
ll ans[30][30][30];
ll w(ll a,ll b,ll c){
    if(a<=0||b<=0||c<=0)return 1;
    if(a>20||b>20||c>20)a=b=c=20;
    if(ans[a][b][c])return ans[a][b][c];
    if(a>20||b>20||c>20)return ans[20][20][20]=1048576;
    if(a<b&&b<c)return ans[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
    else return ans[a][b][c]=w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}
int main(){
    ll i,j,k,m,n,a,b,c;
    while(scanf("%lld%lld%lld",&a,&b,&c)!=EOF){
        if(a==-1&&b==-1&&c==-1)return 0;

        printf("w(%lld, %lld, %lld) = %lld\n",a,b,c,w(a,b,c));
    }
    return 0;
}

啊,记得long long !!!!!!!!

POJ1088

#include<bits/stdc++.h>
using namespace std;
int a[111][111],ans[111][111],n,m;
int go[4][2]={ {1,0},{-1,0},{0,1},{0,-1} };
bool pd(int x,int y){
    if(x<0||y<0||x>n+1||y>m+1)return false;
    return true;
}
int dfs(int x,int y){
    if(ans[x][y]!=1)return ans[x][y];
    //printf("dfs : %d %d\n",x,y);
    for(int i=0;i<4;i++){
        int u=x+go[i][0];
        int v=y+go[i][1];
        //if(p[u][v])continue;
        if(!pd(u,v))continue;
        if(a[x][y]>a[u][v]){
            ans[x][y]=max(ans[x][y],dfs(u,v)+1);
        }
    }
    return ans[x][y];
}
int main(){
    int i,j,k;
    cin>>n>>m;
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++){
            cin>>a[i][j];
            ans[i][j]=1;
        }
    int ANS=0;
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++){
            //printf("Start dfs %d %d : \n",i,j);
            ANS=max(ANS,dfs(i,j));
            //cout<<endl;
        }
    /*
    for(i=1;i<=n;i++,cout<<endl)
        for(j=1;j<=m;j++)cout<<ans[i][j]<<" ";
    */
    cout<<ANS<<endl;
    return 0;
}

显然我是不会告诉你们我忘记边界条件是x<0啊x>n+1,显然我也不会告诉你们我没有把dfs的结果+1更新了。。。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值