Diary 10.4.2014

11 篇文章 0 订阅
6 篇文章 0 订阅

Ask:你昨天的题解呢? Ans:太水了就懒得写了233

嗯刚刚发生了什么?好像有什么奇怪的东西被划掉了。。

反正跟我没关系23333

嗯。。今天贪心专场。。

1. 引爆炸弹(bomb.pas/c/cpp)
【问题描述】
有n个炸弹,有些炸弹牵了一根单向引线(也就是说引线只有在这一端能被炸弹点燃),只要引爆了这个炸弹,用引线连接的下一个炸弹也会爆炸。每个炸弹还有个得分,当这个炸弹被引爆后就能得到相应得分。现在要你引爆k个炸弹,使得得分最大。
【输入】
第一行两个整数n、k。
接下来的n行,每行两个整数a[i]、b[i]。a[i]表示这个炸弹用引线连接的下一个炸弹,如果a[i]为0,则表示这个炸弹没有连接引线。b[i]表示这个炸弹的得分。
【输出】
最多可分成的队数。


本来是没思路的,,然后一不小心看了Clarkok的博客。。

先把边反向,搞一个虚拟根0,然后DFS

如果向下有分叉,就只连接最大的那个,剩下叉掉

然后找前k大。。

const 	shuru='bomb.in';
	    shuchu='bomb.out';
		rp=10086;
		maxn=200000+1;
		orz='Orz ZBT get full mark';
		OTZ='Orz Daily-AK LZW';
		OTL='Orz xudyh';
var num,a,headlist,t,next:array[0..maxn] of int64;
	sign,hash:Array[0..maxn] of boolean;
	b:Array[0..maxn] of int64;
	ans,change,p,x,j,k,n:int64;
	i:longint;
	sad:boolean;
procedure init;
begin	
	fillchar(hash,sizeof(hash),false);
	assign(input,shuru);
	assign(output,shuchu);
	reset(input);
	rewrite(output);
	readln(n,k);
	for i:=0 to n do headlist[i]:=-1;
	for i:=1 to n do
	begin
		readln(x,a[i]);
		inc(p);
		next[p]:=headlist[x];
		headlist[x]:=p;
		t[p]:=i;
	end;
	a[0]:=0;
	close(input);
end;
Procedure dfs(u:longint);
var i,step,step1:longint;
begin
	hash[u]:=true;
	if headlist[u]=-1 then begin
							num[u]:=a[u];
							exit;
						   end;
	if next[headlist[u]]=-1 then begin
									dfs(t[headlist[u]]);
									num[u]:=num[t[headlist[u]]]+A[u];
								 end;
	i:=headlist[u];
	step:=0;
	while i<>-1 do
	begin
		dfs(t[i]);
		if num[t[i]]>Step then begin
								step:=num[t[i]];
								step1:=t[i];
							   end;
		i:=next[i];
	end;
	num[u]:=step+a[u];
	i:=headlist[u];
	while i<>-1 do
	begin
		if t[i]<>step1 then sign[t[i]]:=true;
		i:=next[i];
	end;
end;
procedure qsort(left,right:longint);
var i,j,mid:longint;
begin
	i:=left; j:=right; mid:=b[(i+j) div 2];
	repeat
		while b[i]>mid do inc(i);
		while b[j]<mid do dec(j);
		if i<=j then begin
						change:=b[i];
						b[i]:=b[j];
						b[j]:=change;
						inc(i); dec(j);
					 end;
	until i>j;
	if j>left  then qsort(left,j);
	if i<right then qsort(i,right);
end;
Procedure main;
begin
	init;
	dfs(0);
	sign[0]:=true;
	sad:=true;
	for i:=0 to n do sad:=sad and hash[i];
	if sad=false then begin
						writeln('丧心病狂');
						halt;
					  end;
	p:=0;
	for i:=0 to n do
		if sign[i] then begin
							inc(p);
							b[p]:=num[i];
						end;
	qsort(1,p);
	for i:=1 to k do
		ans:=ans+b[i];
	writeln(ans);
	close(output);
end;
begin
	main;
end.


2. 取石子(stone.pas/c/cpp)
【问题描述】 有n个石子围成一圈,每个石子都有一个权值a[i]。给你一次且仅一次取石子的机会,取石子的块数不限,取完后统计得分。现在要使取出的石子得分最大。
每个石子的得分计算公式是a[i]*d,d表示这个石子到两边被取了的石子的距离和。如{1,2,7,9,8,6,4,5,3,10}这些权值的石子围成一圈,不同取法有不同得分:
【输入】 第一行一个整数n。接下来n行,每行一个整数a[i]。

嗯想到是贪心专场,所以往贪心上想。。

想了半天,没想出来,觉得是个神贪心。。

后来发现真的是‘神’贪心啊

我们发现取3 个石子和3 个以上石子一定不会得到最优解。那么只可能是取两个或者一个石子,设max1 表示所有石子中权值最大的一个,max2 表示所有石子中权值第二大的一个,那么答案一定是Max{(max1+max2)*(n-2),max1*(n-1)}

然后找最大和第二大的程序写错了就只有40分了233 我是傻叉我骄傲!

const shuru='stone.in';
	  shuchu='stone.out';
	  rp=10086;
	  orz='Daily-AK Lzw';
	  OTZ='Daily-AK yyl';
	  OTL='Daily-AK zbt';
	  SCH='Daily-00 wjz';
var t,k,n,x:int64;
	a:Array[0..100000] of int64;
	i,j:longint;
Function max(a,b:int64):int64;
begin
	if a>b then exit(A);
	exit(b);
end;
procedure init;
begin
	assign(input,shuru);
	assign(output,shuchu);
	reset(input);
	rewrite(output);
	readln(n);
	for i:=1 to n do
		readln(a[i]);
end;
procedure qsort(left,right:longint);
var i,j,mid:longint;
begin
	i:=left; j:=right; mid:=a[(i+j) div 2];
	repeat	
		while a[i]<mid do inc(i);
		while a[j]>mid do dec(j);
		if i<=j then begin
						t:=a[i];
						a[i]:=a[j];
						a[j]:=t;
						inc(I); dec(j);
					 end;
	until i>j;
	if j>left  then qsort(left,j);
	if i<right then qsort(i,right);
end;
procedure main;
begin
	init;
	qsort(1,n);
	writeln(max(a[n]*(n-1),(a[n]+a[n-1])*(n-2)));
	close(output);
end;
begin
	main;
end.

T3


嗯。。

我今天写题解的主要原因就是因为这一题

因为这代表了一类DP

具体描述起来就是

有多种物品需要被制造,每种物品有制造的时间,求利益最大什么什么的这样

【问题描述】
一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成m个模块,由公司里的技术人员分工完成,每个技术人员完成同一软件的不同
YZOI-NOIP2014 第二轮模拟(二)day1 ~ 2 ~
模块的所用的天数是相同的,并且是已知的,但完成不同软件的一个模块的时间是不同的,每个技术人员在同一时刻只能做一个模块,一个模块只能由一个人独立完成而不能由多人协同完成。一个技术人员在整个开发期内完成一个模块以后可以接着做任一软件的任一模块。写一个程序,求出公司最早能在什么时候交付软件。
【输入】输入文件第一行包含两个由空格隔开的整数n和m,其中1≤n≤100,1≤m≤100。接下来的n行每行包含两个用空格隔开的整数d1和d2,d1表示该技术人员完成第一个软件中的一个模块所需的天数,d2表示该技术人员完成第二个软件中的一个模块所需的天数,其中l≤d1,d2≤100。
【输出】输出文件仅有一行包含一个整数d,表示公司最早能于d天后交付软件。

嗯就是像这样子的题目。。

这样子通常是怎么样子呢。。通常是把时间,以及做的件数放在状态里

比如上面那个例子就是f[i,j]就是前i个程序员在k(已给出)时间内做了i个n任务后最多能做多少m任务

这道题也是,就是f[i,a,b,c]表示前i-1个已经放好,现在有a个a,b个b,c个c,接下来最少要装多少次箱?

那么通过 f[i][A][B][C]可以正向推出3 个决策
把A装箱:f[i+A][A’][B+B’][C+C’],其中A’,B’,C’表示流水线上第i 到第i+A-1
个产品中分别有多少个A 类,B 类,C 类产品。
把 B 装箱:f[i+B][A+A’][B’][C+C’],其中A’,B’,C’表示流水线上第i 到第i+B-1
个产品中分别有多少个A 类,B 类,C 类产品。
把 C 装箱:f[i+C][A+A’][B+B’][C’],其中A’,B’,C’表示流水线上第i 到第i+C-1
个产品中分别有多少个A 类,B 类,C 类产品。
f[i][A][B][C]=min{f[i+A][A’][B+B’][C+C’],f[i+B][A+A’][B’][C+C’],f[i+C][A+A’][B+B’][C’]}+1



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值