[2016.7.test1] T2 偷天换日 [codevs 1163 访问艺术馆(类似)]

偷天换日
(steal.c/pas/cpp limit 1s 64M)

【问题描述】
神偷对艺术馆内的名画垂涎欲滴准备大捞一把。艺术馆由若干个展览厅和若干条走廊组成。每一条走廊的尽头不是通向一个展览厅,就是分为两个走廊。每个展览厅内都有若干幅画,每副画都有一个价值。经过走廊和偷画都是要耗费时间的。警察会在n秒后到达进口,在不被逮捕的情况下你最多能得到的价值。
【输入文件】
第一行一个整数 n
第二行若干组整数,对于每组整数(t,x),t表示进入这个展览厅或经过走廊要耗费t秒的时间,若x>0表示走廊通向的展览厅内有x幅画,接下来x对整数(w,c)表示偷一幅价值为w的画需要c秒的时间。若x=0表示走廊一分为二。
输入是按深度优先给出的。
【输出文件】
仅一个整数,表示能获得的最大价值。
【输入样例】
50
5 0 10 1 10 1 5 0 10 2 500 1 1000 2 18 1 1000000 4
【输出样例】
1500
【数据规模】
n≤600
t,c≤5;
x≤30
房间和走廊数不超过300个。
【提示】
样例的输入对应于下图

codevs 1163 是本题弱化。

CV 1163 AC code:

#include <iostream>
#include <cstring>
#define ref(i,x,y) for(int i=x;i<=y;i++)
#define def(i,x,y) for(int i=x;i>=y;i--)
#define smax(i,j) i=max(i,j)//要善于用#define
using namespace std;
int tim,len,ans,f[101][601];
int dfs(int fa)//返回这个结点序号
{
    int l,v;
    len++;
    int son=len;//这个结点序号,在最后返回
    cin>>l>>v;//l是路径长度,v是藏画数量
    l*=2;//路径要来回走,乘2
    if (v==0)//不是叶子节点
    {
        int s1,s2;
        s1=dfs(son);//左孩子
        s2=dfs(son);//右孩子
        ref(i,0,tim-l)//只走左边或只走右边
            f[son][i+l]=max(f[s1][i],f[s2][i]);
        ref(i,0,tim-l)//枚举左孩子耗费时间
            ref(j,0,tim-l-i)//枚举右孩子耗费时间
                smax(f[son][i+j+l],f[s1][i]+f[s2][j]);//两边都走
        def(i,tim,5*v)//根据贪心策略,非叶子结点的画要取完
            smax(f[son][i],f[son][i-5*v]+v);
    }
    else //是叶子节点
        ref(i,1,v)//取i个画像
            f[son][i*5+l]=i;
    return son;//返回值,方便记录父亲左孩子和右孩子的序号
}
int main()
{
    cin>>tim;
    memset(f,0,sizeof f);//养成好习惯
    dfs(0);//深搜中输入
    ref(i,0,tim)//取最优答案
        smax(ans,f[1][i]);
    cout<<ans;
}

升级版偷天换日:
ACcode

#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdlib.h>
#include <time.h>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<algorithm>
#include <limits.h>
#include<cmath>
#include<map>
#include<queue>
#include<set>
using namespace std;

#define N 100005
#define M 100005
#define LL long long

//为自己加油O(∩_∩)O~

const long long  mod =1000000007;
int T;
vector<int> v[333];
struct node{
    int w,c;
};
vector<node> dian[333];
int len[333];
int tot=0;

void init(int fa)
{
    tot++;
    int t,x;
    scanf("%d%d",&t,&x);
    len[tot]=t;
    v[fa].push_back(tot);
    if (x>0){
        int w,c;
        for (int j=0;j<x;j++){
            scanf("%d%d",&w,&c);
            dian[tot].push_back(node{w,c});
        }
    }else {
        int now=tot;
        init(now);
        init(now);
    }
}

int dp[333][602];
int f[602];
void suan(int pos)
{
    if (v[pos].empty()){
        for (int j=0;j<dian[pos].size();j++){
            int w=dian[pos][j].w,c=dian[pos][j].c;
            for (int k=600-c;k>=0;k--){
                dp[pos][k+c]=max(dp[pos][k+c],dp[pos][k]+w);
            }
        }
        return;
    }else {
        int l=v[pos][0],r=v[pos][1];
        suan(l);
        suan(r);
        memset(f,0,sizeof(f));
        for (int j=0;j+2*len[l]<=600;j++) dp[pos][j+2*len[l]]=f[j+2*len[l]]=dp[l][j];
        for (int j=0;j+2*len[r]<=600;j++) {
            for (int k=0;k+j+2*len[r]<=600;k++){
                dp[pos][k+j+2*len[r]]=max(dp[pos][k+j+2*len[r]],f[k]+dp[r][j]);
            }
        }
    }
}
int main()
{
    freopen("steal.in","r",stdin);
    freopen("steal.out","w",stdout);
    scanf("%d",&T);
    T-=1;
    init(0);
    suan(1);
    if (T-len[1]*2>=0) printf("%d\n",dp[1][T-2*len[1]]);
    else printf("0\n");
    return 0;
}

你可能感兴趣的:(dp)