【题解】 bzoj4472: [Jsoi2015]salesman (动态规划)

bzoj4472,懒得复制,戳我戳我

Solution:

体面意思:从\(1\)号节点出发,每到一个节点就必须停下,获得节点权值(每个节点只会获得一次),每个点有个规定的停留次数,求最大可获得多大权值,并且判断是否只有唯一的路线才能获得这个权值

  • 直接\(dp\)储存子树最大获得权值就行,顺便要记录方案是否唯一,所以我们可以拿一个结构体来记录
  • \(dp\)权值思路:找出所有子树中前\(vis[i]-1\)大的节点权值(只选大于\(0\)的权值)。
  • \(dp\)方案思路: 1.如果有选择的节点是方案不唯一的,该子树根节点也是方案不唯一。 2. 如果有子节点权值为\(0\),该子树根节点方案不唯一。 3.如果选择的最后一个和不选择的第一个权值一样(且都大于\(0\)),该子树根节点方案不唯一。

Attention:

  • 记录子树的结构体时用\(vector\)更好,不然容易超时越界一堆问题(不会用\(vector\)强行卡代码时间卡过去了)

Code:

//It is coded by Ning_Mew on 4.22
#include<bits/stdc++.h>
using namespace std;

const int maxn=1e5+7;

int read(){
  int x=0,f=1;char ch=getchar();
  while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
  while(ch>=‘0‘&&ch<=‘9‘)x=x*10+ch-‘0‘,ch=getchar();
  return x*f;
}

int n,val[maxn],fa[maxn],vis[maxn];
struct Node{
  int val;bool uni;
  Node(){val=0;uni=false;}
}node[maxn];

int head[maxn],cnt=0;
struct Edge{int nxt,to;}edge[maxn*2];

void add(int from,int to){
  edge[++cnt].nxt=head[from];
  edge[cnt].to=to;
  head[from]=cnt;
}

bool cmp(const Node &x,const Node &y){return x.val>y.val;}

void dfs(int u){
  bool son=false;
  Node box[maxn/128];int ct=0;

  for(int i=head[u];i!=0;i=edge[i].nxt){
    int v=edge[i].to;if(v==fa[u])continue;
    fa[v]=u;son=true;
    dfs(v);
    ct++; box[ct]=node[v];
  }
  if(!son){node[u].val=val[u]; node[u].uni=false;return;}

  sort(box+1,box+ct+1,cmp);

  for(int i=1;i<=min(vis[u]-1,ct);i++){
    if(box[i].val>=0){
      node[u].val+=box[i].val;
      if(box[i].uni)node[u].uni=true;
      if(box[i].val==0){node[u].uni=true;break;}
    }else break;
  }
  node[u].val+=val[u];
  if(vis[u]-1<ct&&box[ vis[u] ].val==box[ vis[u]-1 ].val&&box[ vis[u] ].val>=0)node[u].uni=true;
  return;
}
int main(){
  //freopen("in.in","r",stdin);
  memset(head,0,sizeof(head));cnt=0;
  scanf("%d",&n);
  vis[1]=maxn;
  for(int i=2;i<=n;i++)/*val[i]=read();*/scanf("%d",&val[i]);
  for(int i=2;i<=n;i++)/*vis[i]=read();*/scanf("%d",&vis[i]);
  for(int i=1;i<=n-1;i++){
    int u,v;/*u=read();v=read();*/scanf("%d%d",&u,&v);
    add(u,v);add(v,u);
  }
  dfs(1);
  printf("%d\n",node[1].val);
  if(!node[1].uni)printf("solution is unique\n");
  else printf("solution is not unique\n");
  return 0;
}

原文地址:https://www.cnblogs.com/Ning-Mew/p/8930991.html

时间: 2024-10-12 07:17:45

【题解】 bzoj4472: [Jsoi2015]salesman (动态规划)的相关文章

[BZOJ4472] [Jsoi2015]salesman(DFS/排序)

4472: [Jsoi2015]salesman Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 80  Solved: 45[Submit][Status][Discuss] Description 某售货员小T要到若干城镇去推销商品,由于该地区是交通不便的山区,任意两个城镇之间都只有唯一的可能经过其它城镇的路线. 小T 可以准确地估计出在每个城镇停留的净收益.这些净收益可能是负数,即推销商品的利润抵不上花费.由于交通不便,小T经过每个城镇都需要

bzoj4472: [Jsoi2015]salesman(树形dp)

Description 某售货员小T要到若干城镇去推销商品,由于该地区是交通不便的山区,任意两个城镇之间都只有唯一的可能经过其它城镇的路线. 小T 可以准确地估计出在每个城镇停留的净收益.这些净收益可能是负数,即推销商品的利润抵不上花费.由于交通不便,小T经过每个城镇都需要停留,在每个城镇的停留次数与在该地的净收益无关,因为很多费用不是计次收取的,而每个城镇对小T的商品需求也是相对固定的,停留一次后就饱和了.每个城镇为了强化治安,对外地人的最多停留次数有严格的规定.请你帮小T 设计一个收益最大的

[题解][SHOI2013]超级跳马 动态规划/递推式/矩阵快速幂优化

这道题... 让我见识了纪中的强大 这道题是来纪中第二天(7.2)做的,这么晚写题解是因为 我去学矩阵乘法啦啦啦啦啦对矩阵乘法一窍不通的童鞋戳链接啦 层层递推会TLE,正解矩阵快速幂 首先题意就是给你一个 n 行m 列 的格子图 一只马从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行. 题意很简单暴力dp的思路也很简单但是数据很恶心虽然远古一点,但毕竟是省选题 1 ≤ n ≤ 50,2 ≤ m ≤ 10^9 不过还是给了我们一点提示:n这么小? 总之我们先找出转移式对于每一个点

[JSOI2015] salesman

题面 题解 考虑树形 DP , 设 \(f[i]\) 为 \(i\) 节点为根的子树最大收益是多少, \(h[i]\) 代表 \(i\) 节点的最优方案是否唯一 转移的话拿个堆记一下子节点中 \(>0\) 的那些, 然后 \(h\) 跟他们的与一下 若是剩下来的有 \(f = 0\) 或是跟你选的是一样的, 这个点 \(i\) 的 \(h\) 就计为 \(0\) Code #include <algorithm> #include <iostream> #include &l

[题解+总结]20151010

1.前言 又是绿书上的题目.这种画风感觉还是好些的,虽然都是远古时代的.今天题目感觉难度适中,但是太过于偏向动态规划了吧...还有搜索傻逼题乱入. 2.Sort 产品排序 大概题意:给出n个产品,每个产品有加工时间和冷却时间.现有两台加工机,每台加工机同一时间只能加工一个产品.产品加工完后就进入冷却时间.要求在尽可能短的时间内完成所有产品的所有工序,求最短时间. 题解: 动态规划.设存在两个产品x和y,y的冷却时间大于x,且x排在y之前.如果x和y是相邻的,可以发现在这种情况下完成时间是max{

Bzoj 3450: Tyvj1952 Easy 期望/概率,动态规划

3450: Tyvj1952 Easy Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 431  Solved: 325[Submit][Status][Discuss] Description 某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:(我们来简化一下这个游戏的规则有n次点击要做,成功了就是o,失败了就是x,分数是按comb计算的,连续a个comb就有a*a分,comb就是极大的连续o.比如ooxxxxooooxxx

分享会之动态规划

一.简介 有这样一种具有特殊性的过程,其可以将被分成若干相互联系的阶段,在它的每个阶段都要做出决策,从而使整个过程达到最好的活动效果.但各个阶段决策的选取不是任意的,依赖于当前面临的状态,又影响以后的发展,当各个阶段决策确定后,就组成一个决策序列,因而也就确定了整个过程的一条活动路线. 在求解这种活动过程的最优化结果的时候,通常有4种思路,①暴力穷举:将所有可能的决策序列枚举出来,然后比较每个序列的结果,得到最好的:②简单递归:自顶向下,以边界条件作为递归的结束:③备忘录算法:将每一阶段的决策保

百度之星2017 HDU 6114 Chess 组合数学

Chess 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6114 Description 車是中国象棋中的一种棋子,它能攻击同一行或同一列中没有其他棋子阻隔的棋子.一天,小度在棋盘上摆起了许多車--他想知道,在一共N×M个点的矩形棋盘中摆最多个数的車使其互不攻击的方案数.他经过思考,得出了答案.但他仍不满足,想增加一个条件:对于任何一个車A,如果有其他一个車B在它的上方(車B行号小于車A),那么車A必须在車B的右边(車A列号大于車B).现在要问问

AC日记——丑数 codevs 1246

1246 丑数 USACO 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 对于一给定的素数集合 S = {p1, p2, ..., pK}, 来考虑那些质因数全部属于S 的数的集合.这个集合包括,p1, p1p2, p1p1, 和 p1p2p3 (还有其它).这是个对于一个输入的S的丑数集合.注意:我们不认为1 是一个丑数.你的工作是对于输入的集合S去寻找集合中的第N个丑数.longint(signe