boj 1345 二叉树问题 简单的dp

http://acm.scs.bupt.cn/onlinejudge/showproblem.php?problem_id=1345

 

1.从底向上复杂度比较低。

2.简单的dp应该熟悉。

 

Travel Submit: 349    Accepted:81 Time Limit: 1000MS  Memory Limit: 65536K

Description
Yicou经常旅游,但很可惜他不太喜欢旅游(人在江湖,身不由己阿~)所以,每次yicou到了一个景点以后,就会通过景点地图,寻找最少时间走出景区的路线。
这天,yicou一群人,在FJ的带领下去旅游,不过yicou并不关心去的是哪里,他只想着赶快走出去回去编程。在拿到地图的时候,他惊奇的发现。整个景区竟然是一颗高度为h完全二叉树!最后一行的叶结点全都连接着出口!而入口正好连接着是树根。每个点都只能走向其两个子结点。并且这张地图很好的标出了,每个景点观光时间(从0到99)(路程时间忽略不计)。现在,yicou需要你帮助他寻找从入口到某一出口的最短时间。
不过,在你算完最短时间以后,突然发现,那是一张过期的地图!由于小鱼儿和花无缺的移花接木的影响,很多景点的观光时间变了…(假冒伪略害人不浅阿~)之后你又在小卖部买到了后面一次的更新数据。刚算完新的最短时间,哈哈~,发现还不是最新的,又买了一次更新…一直买了m次,才全都是最新的,而这最后一次算出的才是yicou想要的时间。
不过,你为了向yicou说明,你为了帮他付出了很多努力,yicou需要请你吃饭!你需要把过程中算得的那m次不算数的最短时间,和最后一次算数的最短时间,都给yicou看。
举例:
1
2 5
3 4 6 7
最短为1-2-3 为6

后来第3行第1个数据变为10
1
2 5
10 4 6 7
最短为1-2-4 为7

后来第3行第2个数据变为10
1
2 5
10 10 6 7
最短为1-5-6 为12


再后来第2行第2个数据变为6
1
2 6
10 10 6 7
最短为1-6-6 为13


Input
There are many tests, but only one case in each test.
The first line contain a number h (1<= h <= 16) 代表完全二叉树的高度
Next h lines, each has 2^i (0<=i Next line contain a number m (0<= m <= 10000) 代表更新次数
Next m lines each contains i, j, k means: the ith line’s jth data changes to k
数据准保合乎出题规范,不用判错。


Output
m+1 lines each means a min time

Sample Input

3
1
2 5
3 4 6 7
3
3 1 10
3 2 10
2 2 6


Sample Output

6
7
12
13


Hint
Another Sample Input
4
1
2 3
4 5 6 7
8 9 10 11 12 13 14 15
2
2 2 4
3 1 6

Sample output
15
15
17

#include<iostream>
using namespace std;
int a[(1<<16)];
int dp[1<<16];
int main()   //从下往上 从最后一个非叶结点开始。
{
    int i,j,h,m,x,y,z,total,temp;  //temp:修改的位置  total:总数
    while(scanf("%d",&h)!=EOF)
    {
    total=(1<<h)-1;
    for(i=1;i<=total;i++)
    {
      scanf("%d",&a[i]);
      dp[i]=a[i];
      } 
    for(i=total/2;i>=1;i--)           //最后一个非叶结点
     dp[i]=min(dp[2*i], dp[2*i+1])+a[i];

    printf("%d/n",dp[1]);
    scanf("%d",&m);
    while(m--)
    {
      scanf("%d%d%d",&x,&y,&z);
      temp=(1<<(x-1))-1+y;           //修改的位置
      dp[temp]=dp[temp]+(z-a[temp]);   //修改后 本位置的dp需要加上修改后的值与修改前值的差
      a[temp]=z;
      int i =temp/2;   //从自身的父节点开始变化 
     
      while(i>=1){
            dp[i] = min(dp[2*i+1],dp[2*i]) + a[i];
            if(i ==1) break;
            i =i/2;         //只有自己的祖先节点受影响 别的不用改变
        }
 
      printf("%d/n",dp[1]);     
           }
   

       }//while

    }

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值