Wiki OI 1163 访问艺术馆
来源:互联网 发布:mac智能文件夹怎么用 编辑:程序博客网 时间:2024/04/30 10:15
题目链接:http://wikioi.com/problem/1163/
算法与思路:树形dp,dfs;
将博物馆的结构抽象成一棵二叉树,每条边都有对应的权值(走过这条边花费的时间),
只在叶子节点有藏画,要求你在有限的时间内偷到尽可能多的藏画。
点的信息按照深度优先顺序给出(前序遍历),建立一颗二叉树;
然后从根节点开始深搜,每走过一条走廊到达下一个点,
剩余的时间remain要减去2倍这条走廊的花费,相当于一去一回;
一旦走到叶子节点,尽可能多拿藏画;
状态转移方程dp[root][time] = max{dp[lson][i] + dp[rson][remain - i]} (0 <= i <= remain <= time)
表示在以root为根节点的树中,在时间time内偷到的最多的藏画数;
在当前剩余时间下,枚举在左孩子花费的时间i,剩余的时间分配给右孩子;
并求出所有分配方案下偷到的藏画的最大值。
代码实现:
#include<stdio.h>#include<string.h>using namespace std ;#define N 6500#define T 650int n, m;struct node {int lson, rson, val, cost; }tree[N];struct data{int t, v;}buf[N];int dp[N][T];int max(int x, int y){return x > y ? x : y; }void build(int &x) //按照深度优先顺序(前序遍历)建树 {int root = x;tree[root].cost = 2 * buf[root].t ; //减去经过走廊的来回时间花费tree[root].val = buf[root].v;if(buf[x].v) //判断是否是叶子节点 {tree[root].lson = tree[root].rson = -1; //没有左右孩子 return;}tree[root].lson = x + 1; //左孩子是下一个节点 build(++x); //以左孩子为根节点继续建树 tree[root].rson = x + 1; //右孩子是下一个节点build(++x); //以右孩子为根节点继续建树}int dfs(int root, int time) // dp[root][time]表示在root这个节点(岔口),剩余time时能偷到的最大副画 {if(dp[root][time] != -1) return dp[root][time]; //如果有答案,就结束返回 if(time == 0) return dp[root][time] = 0; //时间还剩0,则一副也偷不到 if(tree[root].lson == -1) //是叶子 {int cnt;if(tree[root].val * 5 <= time - tree[root].cost) cnt = tree[root].val ; //如果经过走廊后的剩余时间可以全部偷完画,直接赋值 else cnt = (time - tree[root].cost) / 5 ; //偷不完就尽可能多拿 return dp[root][time] = cnt; //返回结果 } dp[root][time] = 0; //初始化 int remain = time - tree[root].cost ; //经过走廊后的剩余时间, for(int i = 0; i <= remain; i++) //枚举分配一部分时间给左孩子,剩余时间往右孩子那边去偷 { int s1 = dfs(tree[root].lson, i); //往左孩子方向偷的最多的画 int s2 = dfs(tree[root].rson, remain - i); //往右孩子那边偷的最多的画 dp[root][time] = max(dp[root][time], s1 + s2); //遍历寻求最大值 } return dp[root][time]; }int main(){ int time; n = m = 0; scanf("%d", &time); while(scanf("%d %d", &buf[n].t, &buf[n].v)!=EOF) n++; build(m); //以0为根节点建树 memset(dp, -1, sizeof(dp)); dfs(0, time); printf("%d", dp[0][time]); //0节点,剩余time时间能偷到的最大画就是结果 return 0;}
- Wiki OI 1163 访问艺术馆
- 1163 访问艺术馆
- 1163 访问艺术馆
- CODEVS 1163 访问艺术馆
- CODEVS 1163 访问艺术馆
- 访问艺术馆
- 访问艺术馆
- 【树形DP】wikioi 1163 访问艺术馆
- wikioi 1163 访问艺术馆 树形dp
- CodeVS 1163 访问艺术馆(树形DP)
- Codevs 1163:访问艺术馆——题解
- wikioi p1163 访问艺术馆
- 2014.11.1 访问艺术馆
- codevs1163访问艺术馆
- 【树形dp】访问艺术馆
- Wiki OI 1004 四子连棋
- wiki Oi题解
- 【树形dp】【记忆化】访问艺术馆 WikiOI 1163
- C++语法基础--函数对象,函数对象的函数适配器(绑定器,求反器)
- Code Fragment-使用if return 代替 if else.
- c#中反射的用法(即如何根据字符找到已定义的变量)
- Singleton Pattern
- 如何判断CPU是大端还是小端模式
- Wiki OI 1163 访问艺术馆
- 恭喜您成为 CSDN 博客专家
- maven教程(一)
- 数据库10g和11g之间的数据导出与导入
- 位运算简介及实用技巧(一):基础篇
- leetcode spiral matrix
- DataGridView 列合并
- 找个属于自己的路
- HDU1874:畅通工程续