T1 死亡颂唱者
问题描述
老王沉迷于lol不能自拔,召唤师峡谷是一个树状结构,总共有n个节点(3<=n<=1000),其中每条边的长度均为1,红方英雄全部在叶子节点处,每个叶子节点处都有一个红方英雄。可惜的是蓝方英雄死亡颂唱者经济太过领先,一个大招可以秒掉红方英雄。死亡颂唱者的大招是,在颂唱k秒后(1<=k<=n),对所有敌方英雄造成魔法伤害。前面说了,死亡颂唱者发育的非常好,大招可以秒杀红方英雄。但是红方为了不损失人头,决定在峡谷中一些节点处建造一些温泉使得所有英雄都是安全的。已有的一个基地温泉s(1<=s<=n),死亡颂唱者颂唱k秒,即红方英雄在k秒内到达任意一个温泉即是安全的,英雄的移动速度是1个单位每秒。
输入
第一个数t为数据的组数。对于每一组数据,前三个数分别为n,s,k。后面n-1行,每行2个数a,b。即a,b之间有一条边。
输出
对于每组数据,输出一行,即最少需要修建的温泉数。
样例输入输出
1
14
12 2
1 2
2 3
3 4
4 5
5 6
7 5
8 5
4 9
10 3
2 12
12 14
13 14
14 11
1
问题解决:问题无法解决,只能暴力,结果的确是暴力,什么LCA的的确是想多了。
要点:
(1)直接把s作为根先dfs一遍,更新可以保护以及不能保护的子节点。
(2)贪心原则:对于没能保护的节点,每次选择最深的子节点向上讨论k,直接在k放泉水,然后再以k更新cover数组。
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn=1005;
vector<int> link[maxn],node[maxn];
int father[maxn];
bool cover[maxn];
int n,s,k;
void clear(){
int i,j;
for(i=0;i<=maxn;i++){
link[i].clear();
node[i].clear();
memset(father,0,sizeof(father));
memset(cover,0,sizeof(cover));
//清空函数,为下一组数据做准备
}
}
void dfs(int u,int fa,int depth){
father[u]=fa;
if(link[u].size()==1&&depth>k)node[depth].push_back(u);
//标记K范围以外的子节点
//link[u].size()==1,表示只连了一条边,即为子节点。
int i,j;
for(i=0;i<link[u].size();i++){
if(link[u][i]!=fa)dfs(link[u][i],u,depth+1);
}
}
void dfs2(int u,int fa,int depth){
cover[u]=true;
if(depth==k)return;
int i,j;
for(i=0;i<link[u].size();i++){
int v=link[u][i];
if(v!=fa)dfs2(v,u,depth+1);
}
//更新保护标记
}
int work(){//讨论未被覆盖的叶子节点
int i,j,d,tot=0;
for(d=n-1;d>k;d--){//从最深处开始
for(i=0;i<node[d].size();i++){
int u=node[d][i];
if(cover[u])continue;//该节点已经被保护
int fa=u;
for(j=1;j<=k;j++)fa=father[fa];
dfs2(fa,-1,0);
//贪心原则,直接强行钦点温泉
tot++;
}
}
return tot;
}
int main(){
int t;
cin>>t;
while(t--){
clear();
scanf("%d%d%d",&n,&s,&k);
int i,j;
for(i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
link[a].push_back(b);
link[b].push_back(a);
}
dfs(s,-1,0);
printf("%d\n",work());
}
}
T2 上课不睡觉竟然会死
问题描述
子曰:不睡觉就会死。
深信此话的LYM决定在本学期接下来的n节课上考虑一下睡觉的问题。LYM认为如果在一堂课上睡觉,身体的疲劳值就会下降,反之如果在一堂课上不睡觉,身体的疲劳值就会上升。而身体对疲劳的忍耐是有限度的,一旦疲劳值超过限度,LYM就会go die,于是他不得不在一些课上睡觉。注意,LYM的疲劳值只会在一节课上完后发生改变,如果上完最后一节课后,疲劳值超出了限度,LYM仍然会go die。
不过,在不同的课上,疲劳值的变化量并不总是一样,就如在班主任的课上睡觉,疲劳值并不会下降太多,因为那样会睡得很不安心。
LYM是一个死要面子的人,他宁可冒着生命危险,也要挽回自己在老师心中的形象,因此他不能总是在人家的课上睡觉。他给自己定下了一个规矩:决不连续地在同一主科的课上睡觉,即如果LYM在主科X的某堂课上睡了觉,那么在下一堂(不一定是相邻的)主科
经过了这n节课后,LYM竟然没有死,LYM想知道自己对疲劳值的忍耐极限至少是多少。
输入格式
第一行,一个正整数n.
第二行,n个正整数,表示这n节课的课程安排。每个整数代表一门课程,科目代号对应关系参见下文的表格。(1~6号学科均为主科,7号学科不算作主科).
第三行,n个正整数,其中第i个数表示在第i节课上睡觉,疲劳值的减少量。
第四行,n个正整数,其中第i个数表示在第i节课上不睡觉,疲劳值的增加量。
第五行,一个整数,表示LYM的初始疲劳值。如果初始疲劳值大于了忍耐限度,LYM会在第一节课前就暴亡。
1-6号为主科,7号为其他
输出
一个整数,表示LYM的忍耐限度的最小可能值
样例输入输出
5
7 4 4 5 4
1 6 6 4 4
6 3 8 7 7
8
9
乍一看状态亚索+DP,于是把方程先列出来:
f[i][s] 表示已经上到第i节课,目前睡觉状态为s,最小的忍耐值。
对于其他,管都不管,直接睡——f[i][s]=f[i-1][s]-down[i];
对于主课:
如果睡:
则s&(1<<(a[i]-1))要为true,得到f[i][s]=f[i-1][s^(1<<(a[i]-1))]-down[i];
如果不睡:
对于本来就不能睡的:f[i][s]=min(f[i][s],f[i-1][s^(1<<(a[i]-1))]+up[i]);
对于可以睡但不睡的:f[i][s]=f[i-1][s]+up[i];
但是,状态转移时还应该被疲劳限度所限制,否则中途就可能GO DIE;
在不知道限度的情况下,要进行二分讨论。
#include<stdio.h>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxs=63;
const int maxn=5050;
const int inf=2000000007;
int up[maxn],down[maxn],a[maxn];
int f[maxn][maxn];
int i,n,j,begin0,lasS;
bool ok(int x) {
for(i=0; i<=maxs; i++)f[0][i]=inf;
f[0][0]=begin0;
for(i=1; i<=n; i++) {
if(a[i]==7)
for(lasS=0; lasS<=maxs; lasS++) {
f[i][lasS]=inf;
if(f[i-1][lasS]>x)continue;
f[i][lasS]=f[i-1][lasS]-down[i];
}
else {
for(lasS=0; lasS<=maxs; lasS++) {
f[i][lasS]=inf;
if(lasS&(1<<(a[i]-1))) {
if(f[i-1][lasS^(1<<(a[i]-1))]>x)continue;
f[i][lasS]=f[i-1][lasS^(1<<(a[i]-1))]-down[i];
} else {
if(f[i-1][lasS]<=x) {
f[i][lasS]=f[i-1][lasS]+up[i];
}
if(f[i-1][lasS^(1<<(a[i]-1))]<=x) {
f[i][lasS]=min(f[i][lasS],f[i-1][lasS^(1<<(a[i]-1))]+up[i]);
}
}
}
}
}
for(lasS=0; lasS<=maxs; lasS++) {
if(f[n][lasS]<=x)return true;
}
return false;
}
int find() {
int L=begin0,R=inf,mid;
while(L<=R) {
mid=(L+R)>>1;
if(ok(mid))R=mid-1;
else L=mid+1;
}
return L;
}
int main() {
cin>>n;
for(i=1; i<=n; i++)cin>>a[i];
for(i=1; i<=n; i++)cin>>down[i];
for(i=1; i<=n; i++)cin>>up[i];
cin>>begin0;
cout<<find();
return 0;
}
T3 还没做。。。。。。。