09-Day1 题解

被催着做了Test 09-Day1..

嗯那我就写一下题解了。。

1. 词编码(word.pas/c/cpp)
【问题描述】
一个发送机可以通过一条隧道发送一些以二进制代码组成的单词。在其尽头的接受机可以使用特殊技术恢复到最初的单词。每个单词最初都由0和1组成。所有的单词最初长度都为n(4<=n<=1000)。当穿过隧道之后单词可能发生以下几种情况之一:
(1)任意(一个)0被1取代;
(2)任意(一个)符号被删除;
(3)一个符号(0或1)被插入到任何位置;
(4)不改变。
我们知道最初的单词都具有以下性质:有1的位置号的总和是n+1的倍数,或者是0。
【输入】
n和转换后的单词,每个单词占一行。单词数不大于2001,不会有其他任何东西,除了空格和空行。
【输出】你的程序应该打印输出原始序列的词,注意换行。若有多解,操作4有限,不行则按操作1、2、3优先。同一操作,按操作位置最先的优先(从左到右数起1、2、3…n)。对于操作2,先在被删数列添0,不行再添1。如果没有答案则输出-1。


码农题。。

刚开始没看到原来长度是n被坑了一把。。

const shuru='word.in';
	  shuchu='word.out';
var	s:array[0..1001] of char;
	count,tot,len,i,j,k,n:longint;
	a,d:array[0..1001] of longint;
	sign:boolean;
procedure setIO;
begin
	assign(input,shuru);reset(input);
	assign(output,shuchu);rewrite(output);
	readln(n);
end;
procedure closeIO;
begin
	close(input); close(output);
end;
procedure main;
begin
	setIO;
	while not(eof) do
	begin
		tot:=0; len:=0; count:=0;
		a[0]:=0; sign:=false;
		while not(eoln) do
		begin
			inc(len);
			read(s[len]);
			if s[len]='1' then begin
								inc(tot,len);
								inc(count);
								d[count]:=len;
								a[len]:=a[len-1]+1
							 end
						  else a[len]:=a[len-1];
		end;
		readln;
		if len=n then begin
		if tot mod (len+1)=0 then begin
									for k:=1 to len do write(s[k]);
									writeln;
									continue;
								  end;
		for i:=1 to count do
			if (tot-d[i]) mod (len+1)=0 then begin
												for k:=1 to d[i]-1 do write(s[k]);
												write(0);
												for k:=d[i]+1 to len do write(s[k]);
												writeln;
												sign:=true;
												break;
											 end;
		if sign then continue;
		writeln(-1);
		continue;
					   end;
		if len=n-1 then begin
		for i:=1 to len do
			if (tot+a[len]-a[i-1]) mod (len+2)=0 then begin
														for k:=1 to i-1 do write(s[k]);
														write(0);
														for k:=i to len do write(s[k]);
														writeln;
														sign:=true;
														break;
													end;
		if sign then continue;
		if tot mod (len+2)=0 then begin
									for k:=1 to len do write(s[k]);
									writeln(0);
									continue;
								  end;
		for i:=1 to len do
			if (tot+a[len]-a[i-1]+i) mod (len+2)=0 then begin
														for k:=1 to i-1 do write(s[k]);
														write(1);
														for k:=i to len do write(s[k]);
														writeln;
														sign:=true;
														break;
													end;
		if sign then continue;
		if (tot+len+1) mod (len+2)=0 then begin
											for k:=1 to len do write(s[k]);
											writeln(1);
											continue;
										  end;
		writeln(-1);
		continue;
		end;
		for i:=1 to len do
			case s[i] of
				'0':if (tot-(a[len]-a[i])) mod len=0 then begin
															for k:=1 to i-1 do write(s[k]);
															for k:=i+1 to len do write(s[k]);
															writeln;
															sign:=true;
															break;
														  end;
				'1':if (tot-i-(a[len]-a[i])) mod len=0 then begin
															for k:=1 to i-1 do write(s[k]);
															for k:=i+1 to len do write(s[k]);
															writeln;
															sign:=true;
															break;
														  end;
					end;
		if not(sign) then writeln(-1);
	end;
end;
begin
	main;
end.
		
T2

2. 笨笨粉刷匠(draw.pas/c/cpp)
【问题描述】
笨笨太好玩了,农田荒芜了,彩奖用光了,笨笨只好到处找工作,笨笨找到了一份粉刷匠的工作。
笨笨有n 条木板需要被粉刷。每条木板被分成m 个格子,每个格子要被刷成红色或蓝色。笨笨每次粉
刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色,已知每个格子最多只能被粉刷一次。
如果笨笨只能粉刷t 次,他最多能正确粉刷多少格子。
一个格子如果未被粉刷或被粉刷成错误颜色,就算粉刷错误。
【输入】
第一行三个数n,m,t;
接下来n 行,每行一个长度为m 的字符“0”表示红色,"1"表示蓝色。
【输出】
一个整数,最多能正确粉刷的格子数。

看到题的时候在猜。。猜是DP还是贪心。。

不过觉得贪心不大可能,就想是DP

然后想到了某一行涂k次的DP转移方程。。

设f[i,j]表示前i个涂j次最多能涂对多少个。

f[i,j]:=max(f[i-1,j],f[k,j]+best[k+1,i]){其中best[k+1,j]表示从k+1到j 0和1个数中较大的那个。。

然后发现不会合并。。。

想了很久。。

后来很弃疗地看了lzw大神的博客。。

发现是揹包233333.

以后这种资源分配的需要合并用揹包。。

也算是学到了一点东西吧。。

Code:

const shuru='draw.in';
	  shuchu='draw.out';
	  maxn=51;
	  maxt=2501;
var f:array[0..maxn,0..maxt] of longint;
	a:array[0..maxn,0..maxn] of char;
	p,q:array[0..maxn,0..maxn] of longint;
	v:array[0..maxn,0..maxn] of longint;
	ans:array[0..maxt] of longint;
	pp,step,l,i,j,k,n,m,t:longint;
function min(a,b:longint):longint;
begin
	if a<b then exit(a);
	exit(b);
end;
procedure init;
begin
	assign(input,shuru);reset(input);
	assign(output,shuchu);rewrite(output);
	readln(n,m,t);
	if n*m=t then begin
					writeln(t);
					close(input);close(output);
					halt;
				  end;
	for i:=1 to n do
	begin
		for j:=1 to m do
			read(a[i,j]);
		readln;
	end;
end;
function max(a,b:longint):longint;
begin
	if a>b then exit(a);
	exit(b);
end;
procedure main;
begin
	init;
	step:=min(m,t);
	for k:=1 to n do
	begin
		fillchar(p,sizeof(p),0);
		fillchar(q,sizeof(q),0);
		for i:=1 to m do
			for j:=i to m do
				if a[k,j]='1' then begin
									p[i,j]:=p[i,j-1]+1;
									q[i,j]:=q[i,j-1];
								 end
							else begin
									p[i,j]:=p[i,j-1];
									q[i,j]:=q[i,j-1]+1;
								 end;
		for i:=1 to m do
			for l:=1 to step do
			begin
				f[i,l]:=f[i-1,l];
				for j:=0 to i-1 do
					f[i,l]:=max(f[i,l],f[j,l-1]+max(p[j+1,i],q[j+1,i]));
			end;
		for i:=0 to step do
			v[k,i]:=f[m,i];
	end;
	for k:=1 to n do
		for j:=t downto 0 do
		begin
			pp:=min(j,step);
			for i:=0 to pp do
				ans[j]:=max(ans[j],ans[j-i]+v[k,i]);
		end;
	writeln(ans[t]);
	close(output); close(input);
end;
begin
	main;
end.
3. 笨笨的电话网络(phone.pas/c/cpp)
【问题描述】
多年以后,笨笨长大了,成为了电话线布置师。由于地震使得某市的电话线全部损坏,笨笨是负责将电话线接到该市的负责人。该市周围分布着N(1≤N≤1000)根按1..N顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相连。一共P(1≤P≤10000)对电话线杆间可以拉电话线,其余的由于地震使得无法被连接。
第i对电话线杆的两个端点分别为Ai,Bi,它们间的距离为Li(1≤Li≤1000000)。数据保证每对(Ai,Bi)最多只出现1次。编号为1的电话线杆已经接入了全国的电话网络,整个市的电话线全都连到了编号为N的电话线杆上。也就是说,笨笨的任务仅仅是找一条将1号和N号电话线杆连起来的路径,其余电话线杆并不一定要连入电话网络。
电信公司决定支援灾区免费为该市连接K(0≤K≤N)对由笨笨指定的电话线杆。对于此外的那些电话线,需要为它们付费,总费用等于其中最长的电话线的长度(每根电话线仅连接一对电话线杆)。如果需要连接的电话线杆不超过K对,那么总支出为0。
笨笨需要计算一下,将电话线引到震中市最少需要在电话线上花多少钱?
【输入】
输入文件的第一行包含三个用空格隔开的整数:N,P和K。
第二行到第P+1行:每行分别都为三个用空格隔开的整数:Ai,Bi和Li。
【输出】输出文件中仅包含一个整数,表示在这项工程上的最小支出。如果任务不可能完成,则输出-1。

这题是某一天早上模模糊糊想出来的。。

很明显就是找这样一条路,使它的第k+1大的边最小

这种什么xxx的最小肯定用二分答案,转化成判定问题

二分答案后,对所有的边,如果它大于他,就是1,否则就是0.

然后做最短路,如果小于等于k,就可以的。。

最开始数组开小只拿了30分真是开心。。

const shuru='phone.in';
	  shuchu='phone.out';
	  maxn=1001;
	  maxm=20002;
	  INF=1 shl 26;
	  long=40*maxn;
var	d,headlist:array[0..maxn] of longint;
	weight,w,t,next:Array[0..maxm] of longint;
	queue:array[0..long] of longint;
	inq:Array[0..maxn] of boolean;
	a:Array[0..maxm] of longint;
	l,r,mid,ans,data,front,finish,p,i,j,k,n,m,x,y,z,num:longint;
procedure init;
begin
	assign(input,shuru);reset(input);
	assign(output,shuchu);rewrite(output);
	readln(n,m,k);
	for i:=1 to n do headlist[i]:=-1;
	for i:=1 to m do
	begin
		readln(x,y,z);
		a[i]:=z;
		inc(num);
		next[num]:=headlist[x];
		headlist[x]:=num;
		t[num]:=y;
		weight[num]:=z;
		inc(Num);
		next[num]:=headlist[y];
		headlist[y]:=num;
		t[num]:=x;
		weight[num]:=z;
	end;
	close(input);
end;
procedure qsort(left,right:longint);
var i,j,mid:longint;
begin
	i:=left; j:=right; mid:=a[(i+j) shr 1];
	repeat
		while a[i]<mid do inc(i);
		while a[j]>mid do dec(j);
		if i<=j then begin
						p:=a[i];
						a[i]:=a[j];
						a[j]:=p;
						inc(i);
						dec(j);
					 end;
	until i>j;
	if j>left  then qsort(left,j);
	if i<right then qsort(i,right);
end;
function spfa(sign:longint):longint;
var i:longint;
begin
	w:=weight;
	for i:=1 to num do if w[i]>sign then w[i]:=1 else w[i]:=0;
	fillchar(inq,sizeof(inq),false);
	for i:=1 to n do d[i]:=INF;
	d[1]:=0;
	queue[1]:=1; inq[1]:=true;
	front:=0; finish:=1;
	while front<>finish do
	begin
		inc(front);
		if front>long then front:=front-long;
		x:=queue[front];
		i:=headlist[x];
		inq[x]:=false;
		while i<>-1 do
		begin
			if d[t[i]]>d[x]+w[i] then begin
										d[t[i]]:=d[x]+w[i];
										if not(inq[t[i]]) then begin
																	inc(finish);
																	if finish>long then finish:=finish-long;
																	queue[finish]:=t[i];
																	inq[t[i]]:=true;
															   end;
									  end;
			i:=next[i];
		end;
	end;
	exit(d[n]);
end;
function min(a,b:longint):longint;
begin
	if a<b then exit(a);
	exit(b);
end;
procedure main;
begin
	init;
	data:=spfa(-1);
	if data<=k then begin
						writeln(0);
						close(output);
						halt;
					end;
	if d[n]=INF then begin
						writeln(-1);
						close(output);
						halt;
					 end;
	qsort(1,m);
	l:=1; r:=m; ans:=INF;
	repeat
		mid:=(l+r) shr 1;
		data:=spfa(a[mid]);
		if data<=k then begin
							ans:=min(ans,a[mid]);
							r:=mid-1;
						end
				   else l:=mid+1;
	until l>r;
	writeln(ans);
	close(output);
end;
begin
	main;
end.



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章