首页 > 其他分享 >luoguP1269 信号放大器

luoguP1269 信号放大器

时间:2022-11-18 14:14:14浏览次数:38  
标签:oo ch luoguP1269 ll int 信号 放大器 dp 贪心

神奇的题目
想了3个做法
假·贪心、真·DP、真·贪心
全部交上去
分别获得40、90、100的好成绩
蚌埠住了

1.假·贪心

考虑从孩子节点开始一直到指定的根节点u
到中途某个节点,信号强度不够用了,那么对应根节点u的放大器数+1
这样贪心是不对的,只有WA40分
因为选择某些节点可能会对于之后的整棵子树减少不必要的消费
//...WA40
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll N=2e4+10;

ll read() {

	ll x=0,f=1;
	char ch=getchar();
	while(ch<48||ch>57) {
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>=48&&ch<=57) {
		x=(x<<3)+(x<<1)+(ch^48);
		ch=getchar();
	}
	return x*f;

}

ll head[N],to[N*2],tot=0,nxt[N*2],dis[N*2];

void add(ll u,ll v,ll w) {
	
	nxt[++tot]=head[u];
	to[tot]=v;
	dis[tot]=w;
	head[u]=tot;
	
}

ll n,k,oo,maxx=0,cnt=0;

void dfs(ll u,ll fa,ll energy) {
	
	for(ll i=head[u];i;i=nxt[i]) {
		
		ll v=to[i],w=dis[i];
		if(v==fa) continue;
		if(energy-w<=0) dfs(v,u,oo),cnt++;
		else dfs(v,u,energy-w);
		
	}
	
}

int main() {
	
	n=read();
	for(ll i=1;i<=n;i++) {
		
		k=read();
		for(ll j=1;j<=k;j++) {
			
			ll u=read(),w=read();
			add(i,u,w);
			maxx=max(maxx,w);
			
		}
		
	}
	oo=read();
	if(maxx>=oo) printf("No solution.\n");
	else {
		
		dfs(1,1,oo);
		printf("%lld\n",cnt);
		
	} 
	
	return 0;
} 

2.真·DP

那么考虑dp 
dp[u][0/1] 表示遍历以u为根的子树所需要的放大器数量 0/1表示是否选择u 
动态规划选择最优点 
以此类推,最后答案汇总到根节点1上
然后你就有TLE90分的好成绩?
//...TLE90
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll N=2e4+10;

ll read() {

	ll x=0,f=1;
	char ch=getchar();
	while(ch<48||ch>57) {
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>=48&&ch<=57) {
		x=(x<<3)+(x<<1)+(ch^48);
		ch=getchar();
	}
	return x*f;

}

ll head[N],to[N*2],tot=0,nxt[N*2],dis[N*2];

void add(ll u,ll v,ll w) {

	nxt[++tot]=head[u];
	to[tot]=v;
	dis[tot]=w;
	head[u]=tot;

}

ll n,k,oo,maxx=0,cnt=0;
ll dp[N][2];

void dfs(ll u,ll fa,ll energy) {
	
	dp[u][0]=0;
	dp[u][1]=1;
	for(ll i=head[u]; i; i=nxt[i]) {

		ll v=to[i],w=dis[i];
		if(v==fa) continue;
		if(energy-w>0) {

			dfs(v,u,energy-w);
			dp[u][0]+=min(dp[v][0],dp[v][1]);

		} else {

			dp[u][0]=1e9+7;

		}
		dfs(v,u,oo-w);
		dp[u][1]+=min(dp[v][0],dp[v][1]);

	}

}

int main() {

	n=read();
	for(ll i=1; i<=n; i++) {

		k=read();
		for(ll j=1; j<=k; j++) {

			ll u=read(),w=read();
			add(i,u,w);
			maxx=max(maxx,w);

		}

	}
	oo=read();
	if(maxx>=oo) printf("No solution.\n");
	else {
		
		dfs(1,0,oo);
		printf("%lld\n",min(dp[1][0],dp[1][1]));

	}

	return 0;
}

3.真·贪心

然后你不得不考虑优化贪心算法
鉴于有时候在某个点父亲加放大器可能更优
从子节点开始,再跑贪心,该加的时候加就可以了 
然后就100分了...
//...AC100
//开始一直以为TLE是long long或者手写前向星的问题
//后面改了一下,问题不大
#include <bits/stdc++.h>
#include <vector>
using namespace std;

const int N=2e4+10;

int read() {

	int x=0,f=1;
	char ch=getchar();
	while(ch<48||ch>57) {
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>=48&&ch<=57) {
		x=(x<<3)+(x<<1)+(ch^48);
		ch=getchar();
	}
	return x*f;

}

struct node{
	
	int v,w;
	
};
vector<node> p[N]; 

int n,k,oo,maxx=0,ans=0;
int d[N],dfa[N];

void dfs(int u,int fa) {
	
	for(int i=0; i<p[u].size(); i++) {

		int v=p[u][i].v,w=p[u][i].w;
		if(v==fa) continue;
		dfa[v]=w;
		dfs(v,u);
		d[u]=max(d[u],d[v]+w);

	}
	if(d[u]+dfa[u]>oo) ans++,d[u]=0;

}

int main() {

	n=read();
	for(int i=1; i<=n; i++) {

		k=read();
		for(int j=1; j<=k; j++) {

			int u=read(),w=read();
			p[i].push_back( {u,w} );
			maxx=max(maxx,w);

		}

	}
	oo=read();
	if(maxx>=oo) printf("No solution.\n");
	else {
		
		dfs(1,0);
		printf("%d\n",ans);

	}

	return 0;
}

标签:oo,ch,luoguP1269,ll,int,信号,放大器,dp,贪心
From: https://www.cnblogs.com/Diamondan/p/16903042.html

相关文章

  • FPGA ——防止信号被优化(转载)
    转载:https://blog.csdn.net/weixin_46062412/article/details/125299437Quartus对这种情况的处理是增加约束,共有2种情况:a,需要保留的信号类型是wire在定......
  • Linux下进程间通信方式之管道、信号、共享内存、消息队列、信号量、套接字
    /*1,进程间通信(IPC)Inter-ProcessCommunication比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息。2,linux下IPC机制的分类:管道、信号、共享内存、......
  • 服务器端信号编程
    服务器端程序通常需要处理信号,关于信号的概念不多说,linux操作系统默认有64个信号,用kill-l可列出所有信号,信号是个异步机制的东西,我们这里的信号指的是操作系统给进程或者......
  • 转速测量脉冲信号采集 Modbus模块 编码器脉冲计数器pnp/npn转485
    特点:●编码器解码转换成标准ModbusRTU协议●可用作编码器计数器或者转速测量●支持编码器计数,可识别正反转●也可以设置作为2路独立DI高速计数器●计数值支持断电自动......
  • 进程间通信-信号-pipe-fifo
    一、管道(pipe)1、管道的定义和特点管道是一种两个进程间进行单向通信的机制。因为管道传递数据的单向性,管道又称为半双工管道。管道的这一特点决定了器使用的局限性。管......
  • 进程间通信-信号-pipe-fifo
    进程间通信-信号-pipe-fifopipepipe只能用于有血缘关系的进程进行单向通信。调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端,然后通过fd......
  • 进程间通信-信号-pipe-fifo
    1.信号signal1、信号的名字和编号:每个信号都有一个名字和编号,这些名字都以“SIG”开头,例如“SIGIO”、“SIGCHLD”等等。信号定义在signal.h头文件中,信号名都定义为正......
  • 进程间通信-信号-pipe-fifo
    一、有名管道FIFO1.在有名管道(namedpipe或FIFO)提出后,管道(pipe)限制得到了克服。值得注意的是,FIFO严格遵循先进先出(firstinfirstout),对管道及FIFO的读总是从开始处返回......
  • 进程间通信-信号-pipe-fifo
    进程间通信-信号-pipe-fifo有名管道FIFO无名管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(namedpipe或FIFO)提出后,该限制得到了克......
  • 进程间通信-信号-pipe-fifo
     任务详情编译运行附件中的代码,提交运行结果截图理解代码,特别是相关系统调用的使用。Linux进程间通信进程是程序运行资源分配的最小单位。每个进程各自有不同的用户......