消防局的设立将军令//贪心

2023-10-25 03:51

本文主要是介绍消防局的设立将军令//贪心,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

消防局有DP做法,而且要是按省选难度看的话那个题应该是DP

昨天跟冯神讨论了一下,如果点上设权,那么就只能DP做了

下面DP部分的详细讲解转载自luogu CaptainSlow 的题解(这里是他的博客)

DP[i][state] 表示 i 当前子树根节点
state就是一个一个的状态
state = 0, 1, 2 :
DP[i][0] 表示 选 i 为消防局
DP[i][1] 表示 {至少} 选了 i 的一个儿子为消防局 DP[i][2] 表示 {至少} 选了 i 的一个孙子为消防局 ==================================以上三种状态是 i {一定被消防局覆盖} 的情况 state = 3, 4 : DP[i][3] 表示 i 的 {所有} 儿子节点一定被消防局覆盖 DP[i][4] 表示 i 的 {所有} 孙子节点一定被消防局覆盖 ==================================以上两种状态是 i {不一定被消防局覆盖} 的情况

以下j, k均表示i的儿子节点)
DP[i][0] = 1 + Σ min ( DP[j][0...4] );由于当 i 为消防站之后儿子和孙子是否为消防局就无关紧要,因此状态在0~4中寻找一个MIN,然后还需要+1(因为自己是消防局) DP[i][1] = min ( DP[k][0] + Σ ( j != k ) min ( DP[j][0...3] ) ); 由于儿子为消防站时只能覆盖到兄弟(这里不含所选儿子的儿子),要使选了一个儿子之后子树中包括自己的所有节点都被覆盖,所以除了这个选的儿子,其他儿子的儿子一定要全部被覆盖,状态0~3满足。 DP[i][2] = min ( DP[k][1] + Σ ( j != k ) min ( DP[j][0...2] ) ); 要使选了一个孙子之后合法,由于孙子最多只能覆盖到当前节点,所以其他儿子一定全部覆盖, 状态0~2满足 DP[i][3] = Σ min(DP[j][0...2]); 要使儿子及孙子全部被覆盖,即儿子本身要被覆盖,状态0~2满足 DP[i][4] = Σ min(DP[j][0...3]); 孙子全部被覆盖 ,状态0~3满足
加速:令 DP[i][j] 表示 min ( DP[i][0..k] ) (2<=k<=4)因此可以得到:DP[i][0] = 1 + Σ DP[j][4]; DP[i][1] = DP[i][4] + min ( DP[k][0] - DP[k][3] ); DP[i][2] = DP[i][3] + min ( DP[k][1] - DP[k][2] ); DP[i][3] = Σ DP[j][2]; DP[i][4] = Σ DP[j][3];

正确DP很神,很难设计状态,不太可做

我们可以口胡一个贪心,照样可以A这道题

我们随便pick一个点为根,然后算出每个点的深度

由于深度最深的点必须被覆盖,所以想到覆盖掉它的最好位置就是它的爷爷

为什么不是它的兄弟?因为你是最深的点,设在你的爷爷上必能覆盖你的兄弟,

但是设在兄弟上覆盖不到爷爷的爷爷,从正确性上讲,贪心得到证明

每次用优先队列找深度最大的点

AC代码:

#include<bits/stdc++.h>using namespace std ;const int MAXN = 1010;
struct Edge{int nxt,to;
}edge[MAXN<<1];
int head[MAXN],ectr;
void addedge(int from,int to){edge[++ectr].to = to;edge[ectr].nxt = head[from];head[from] = ectr;
}
int n,dep[MAXN],father[MAXN],book[MAXN];
struct Node{int ID,dep;
};
priority_queue<Node> q;
bool operator < (Node a,Node b){return a.dep < b.dep;
}void dfs1(int x,int fa){dep[x] = dep[fa] + 1;father[x] = fa;for(int i=head[x];i;i=edge[i].nxt){int to = edge[i].to;if(to == fa) continue;dfs1(to,x);}
}int find (int x,int now){if(x == 1 || now == 0) return x;else return find(father[x],now-1);
}void tatoo(int x,int fa,int now){book[x] = true;if(now == 0) return;for(int i=head[x]; i; i=edge[i].nxt){int to = edge[i].to;if(to == fa) continue;tatoo(to, x, now - 1);}
}int main(){cin>>n;for(int i=2;i<=n;++i){int aa;cin>>aa;addedge(aa,i);addedge(i,aa);}for(int i=head[1]; i; i=edge[i].nxt){int to = edge[i].to;dfs1(to,1);}for(int i=1;i<=n;i++){Node xxx;xxx.ID = i;xxx.dep = dep[i];q.push(xxx);}long long ans = 0;while(!q.empty()){Node xxx = q.top();q.pop();if(book[xxx.ID]) continue;++ans;int se = find(xxx.ID,2);
//        cout<<"ans = "<<ans<<" se = "<<se<<endl;tatoo(se,-1,2);}cout<<ans<<endl;return 0;
}

  同时有一道同做法的题,而且只能贪心,叫将军令

  这里贴出AC代码,跟上面差了几个变量名的事

#include<bits/stdc++.h>using namespace std ;const int MAXN = 100010;
struct Edge{int nxt,to;
}edge[MAXN<<1];
int head[MAXN],ectr;
void addedge(int from,int to){edge[++ectr].to = to;edge[ectr].nxt = head[from];head[from] = ectr;
}
int n,k,t,dep[MAXN],father[MAXN],book[MAXN];
struct Node{int ID,dep;
};
priority_queue<Node> q;
bool operator < (Node a,Node b){return a.dep<b.dep;
}void dfs1(int x,int fa){dep[x] = dep[fa] + 1;father[x] = fa;for(int i=head[x];i;i=edge[i].nxt){int to = edge[i].to;if(to == fa) continue;dfs1(to,x);}
}int find (int x,int now){if(x == 1 || now == 0) return x;else return find(father[x],now-1);
}void tatoo(int x,int fa,int now){book[x] = true;if(now == 0) return;for(int i=head[x];i;i=edge[i].nxt){int to = edge[i].to;if(to == fa) continue;tatoo(to, x, now - 1);}
}int main(){cin>>n>>k>>t;for(int i=1;i<n;++i){int a,b;cin>>a>>b;addedge(a,b);addedge(b,a);}for(int i=head[1];i;i=edge[i].nxt){int to = edge[i].to;dfs1(to,1);}for(int i=1;i<=n;i++){Node xxx;xxx.ID = i;xxx.dep = dep[i];q.push(xxx);}long long ans = 0;while(!q.empty()){Node xxx = q.top();q.pop();if(book[xxx.ID]) continue;++ans;int se = find(xxx.ID,k);tatoo(se,-1,k);}
//    cout<<find(3,1);cout<<ans<<endl;return 0;
}
将军令

 

 

 

转载于:https://www.cnblogs.com/SINXIII/p/11261794.html

这篇关于消防局的设立将军令//贪心的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/279839

相关文章

usaco 1.3 Barn Repair(贪心)

思路:用上M块木板时有 M-1 个间隙。目标是让总间隙最大。将相邻两个有牛的牛棚之间间隔的牛棚数排序,选取最大的M-1个作为间隙,其余地方用木板盖住。 做法: 1.若,板(M) 的数目大于或等于 牛棚中有牛的数目(C),则 目测 给每个牛牛发一个板就为最小的需求~ 2.否则,先对 牛牛们的门牌号排序,然后 用一个数组 blank[ ] 记录两门牌号之间的距离,然后 用数组 an

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

POJ2010 贪心优先队列

c头牛,需要选n头(奇数);学校总共有f的资金, 每头牛分数score和学费cost,问合法招生方案中,中间分数(即排名第(n+1)/2)最高的是多少。 n头牛按照先score后cost从小到大排序; 枚举中间score的牛,  预处理左边与右边的最小花费和。 预处理直接优先队列贪心 public class Main {public static voi

ural 1820. Ural Steaks 贪心

1820. Ural Steaks Time limit: 0.5 second Memory limit: 64 MB After the personal contest, happy but hungry programmers dropped into the restaurant “Ural Steaks” and ordered  n specialty steaks

ural 1014. Product of Digits贪心

1014. Product of Digits Time limit: 1.0 second Memory limit: 64 MB Your task is to find the minimal positive integer number  Q so that the product of digits of  Q is exactly equal to  N. Inpu

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

BUYING FEED(贪心+树状动态规划)

BUYING FEED 时间限制: 3000 ms  |  内存限制: 65535 KB 难度:4 描述 Farmer John needs to travel to town to pick up K (1 <= K <= 100)pounds of feed. Driving D miles with K pounds of feed in his truck costs D

vua 10700-Camel trading 贪心以及栈

大意:给一个表达式,可以让你任意套括号,问套完括号最大最小值是多少 贪心策略:最大的话,先+后*                  最小的话,先*后+ 用了一个栈堆模拟运算的次序 #include<stdio.h>#include<iostream>#include<stack>using namespace std;int main(){int N;scanf("%d",&

Commando War-uva 贪心

大意:给你N个任务,你交代他需要J时间,完成他需要B时间,问怎么搭配可以使全部问题完成时话的时间最少 思路:贪心算法,先做完成时间长的,完成时间相同的话先做交代时间长的,用了一下结构体二级快排 #include<stdio.h>#include<string.h>#include<stdlib.h>#define MAX_SIZE 1000 + 10struct Time{int