题目描述
Oliver进入初中后,觉得自己不能总是玩儿了,应该要好好学习了。正好一次考试结束了,Oliver想知道自己的语文,数学,英语分别与语文年级第一,数学年级第一,英语年级第一相差多少。
由于Oliver所在年级有N个人,所以Oliver想你编个程序帮帮他。
思路:
排序,没什么好说
代码:
type arr=array[0..31] of longint;
var n:int64;
i:longint;
a,b,c,m1,m2,m3,x,y,z:string;
function jian(kk,k:string):string;
var aa,bb,cc:array [0..32] of longint;
i,j,la,lb,lc:longint;
begin
if length(kk)then exit('0');
if (length(kk)=length(k)) and (kk<=k) then exit('0');
fillchar(aa,sizeof(aa),0);
fillchar(bb,sizeof(bb),0);
fillchar(cc,sizeof(cc),0);
la:=length(kk);
lb:=length(k);
for i:=1 to la do aa[i]:=ord(kk[la-i+1])-48;
for i:=1 to lb do bb[i]:=ord(K[lb-i+1])-48;
i:=1;
while i<=la do
begin
if aa[i]then
begin
aa[i]:=aa[i]+10;
aa[i+1]:=aa[i+1]-1;
end;
cc[i]:=aa[i]-bb[i];
inc(i);
end;
while cc[i]=0 do dec(i);
jian:='';
for j:=i downto 1 do
jian:=jian+chr(cc[j]+48);
end;
function max(x,y:string):string;
begin
//if x>y then exit(x) else exit(y);
if length(x)=length(y) then
begin
if x>y then exit(x) else exit(y);
end else
if length(x)>length(y) then exit(x) else exit(y);
end;
begin
assign(input,'score.in');
assign(output,'score.out');
reset(input);
rewrite(output);
readln(a);
readln(b);
readln(c);
m1:=a; m2:=b; m3:=c;
readln(n);
for i:=1 to n do
begin
//read(x,y,z);
readln(x);
readln(y);
readln(z);
m1:=max(x,m1); m2:=max(y,m2); m3:=max(z,m3);
end;
write(jian(m1,a),' ',jian(m2,b),' ',jian(m3,c));
close(input);
close(output);
end.
T2
题目描述:
玩过Diablo的人对技能树一定是很熟悉的。一颗技能树的每个结点都是一项技能,要学会这项技能则需要耗费一定的技能点数。只有学会了某一项技能以后,才能继续学习它的后继技能。每项技能又有着不同的级别,级别越高效果越好,而技能的升级也是需要 耗费技能点数的。
有个玩家积攒了一定的技能点数,他想尽可能地利用这些技能点数来达到最好的效果。因此他给所有的级别都打上了分,他认为效果越好的分数也越高。现在他要你帮忙寻找一个分配技能点数的方案,使得分数总和最高。
思路:
树形DP
设l1[i][j]表示为第i个技能j级的位置(即输入顺序)
设a[i][0]表示技能i的前继技能和上一级的个数
a[i][j]表示技能i的第j级的前继技能和上一级的位置
要求出对于任何一个结点的后继结点和前继结点、相应的技能点(f[i])和分数(w[i])
然后,对于i的父亲名字==j的名字(就是j是i的前继技能),那么a[l1[j][1]][0]++,a[l1[++y,1],a[l1[y,1],0]]=l1[i,1](就是求出对于i结点的前继技能)
于是要造一棵树,表示对于每个结点的要学的两个端点(也就是说对于i结点要学的技能就在[l..r]这个区间内)
设dp[i][j]表示为从i出发,用了j技能点的最大分数值,那么状态转移方程就是dp[x][i]=max(dp[r[x]][i],dp[l[x]][j]+dp[r[x]][i-j-f[x]]+w[x])
0<=i<=p,1<=j<=i-f[x]
代码:
uses math;
var n,m,x,y,s,root,p:longint;
l1:array[0..20,0..20] of longint;
l,r,f,w:array[0..400]of longint;
a:array[0..400,0..400]of longint;
dp:array[-1..400,0..100]of longint;
name,fname:array[0..20]of string;
procedure build(t:longint);
var i:longint;
begin
for i:=1 to a[t,0]-1 do r[a[t,i]]:=a[t,i+1];
if a[t,0]>0 then l[t]:=a[t,1];
for i:=1 to a[t,0] do build(a[t,i]);
end;
procedure init;
var i,j:longint;
begin
assign(input,'skill.in');
assign(output,'skill.out');
reset(input);
rewrite(output);
readln(n);
for i:=1 to n do
begin
readln(name[i]);
readln(fname[i]);
readln(s);
for j:=1 to s do
begin
inc(x);
l1[i,j]:=x;
read(y);
f[x]:=y;
if j>1 then
begin
inc(a[l1[i,j-1],0]);
a[l1[i,j-1],a[l1[i,j-1],0]]:=l1[i,j];
end;
end;
readln;
for j:=1 to s do
begin
read(y);
w[l1[i,j]]:=y;
end;
readln;
end;
for i:=1 to n do
begin
y:=root;
for j:=1 to n do
if (fname[i]=name[j]) then
begin
y:=j;
break;
end;
inc(a[l1[y,1],0]);
a[l1[++y,1],a[l1[y,1],0]]:=l1[i,1];
end;
readln(p);
for i:=1 to n do
begin
read(y);
for j:=1 to y do
begin
w[l1[i][j]]:=0;
f[l1[i][j]]:=0;
end;
end;
for i:=0 to x do
begin
l[i]:=-1;
r[i]:=-1;
end;
build(root);
end;
procedure tdp(x:longint);
var i,j:longint;
begin
if x<0 then exit;
tdp(l[x]);
tdp(r[x]);
for i:=0 to p do
begin
dp[x,i]:=dp[r[x],i];
for j:=0 to i-f[x] do
dp[x,i]:=max(dp[x,i],dp[l[x],j]+dp[r[x],i-j-f[x]]+w[x]);
end;
end;
begin
init;
tdp(root);
writeln(dp[root,p]);
close(input);
close(output);
end.
T3
题目描述:
DaA 和他的朋友组成一个团队去旅行了。他们每个人都准备了一个背包,用来装旅行用的物品。他们的背包有两个特点:
1. 每个人的背包能装无限多的物品,每种物品有一个价值,但只能装一件;
2. 每个人都很有个性,所以每个人的背包不会完全相同。
DaA 的团队中有M 个人,那么对于整个团队,背包价值和最大是多少呢?
思路:
贪心+递推
因为每件物品在每个背包只能装一个,那么设f[i]来表示分数值为i的情况有多少种
递推式就是f[i]=f[i-w[i]]+f[i]
然后downto,用贪心得出最大可能性ans,这里的贪心有两种操作:
①如果f[i]<=m
ans=ans+i*f[i];
m=m-f[i]
②如果f[i]>m
ans=ans+i*m
break
代码:
uses math;
var n,m,x,y,s,root,p:longint;
l1:array[0..20,0..20] of longint;
l,r,f,w:array[0..400]of longint;
a:array[0..400,0..400]of longint;
dp:array[-1..400,0..100]of longint;
name,fname:array[0..20]of string;
procedure build(t:longint);
var i:longint;
begin
for i:=1 to a[t,0]-1 do r[a[t,i]]:=a[t,i+1];
if a[t,0]>0 then l[t]:=a[t,1];
for i:=1 to a[t,0] do build(a[t,i]);
end;
procedure init;
var i,j:longint;
begin
assign(input,'skill.in');
assign(output,'skill.out');
reset(input);
rewrite(output);
readln(n);
for i:=1 to n do
begin
readln(name[i]);
readln(fname[i]);
readln(s);
for j:=1 to s do
begin
inc(x);
l1[i,j]:=x;
read(y);
f[x]:=y;
if j>1 then
begin
inc(a[l1[i,j-1],0]);
a[l1[i,j-1],a[l1[i,j-1],0]]:=l1[i,j];
end;
end;
readln;
for j:=1 to s do
begin
read(y);
w[l1[i,j]]:=y;
end;
readln;
end;
for i:=1 to n do
begin
y:=root;
for j:=1 to n do
if (fname[i]=name[j]) then
begin
y:=j;
break;
end;
inc(a[l1[y,1],0]);
a[l1[++y,1],a[l1[y,1],0]]:=l1[i,1];
end;
readln(p);
for i:=1 to n do
begin
read(y);
for j:=1 to y do
begin
w[l1[i][j]]:=0;
f[l1[i][j]]:=0;
end;
end;
for i:=0 to x do
begin
l[i]:=-1;
r[i]:=-1;
end;
build(root);
end;
procedure tdp(x:longint);
var i,j:longint;
begin
if x<0 then exit;
tdp(l[x]);
tdp(r[x]);
for i:=0 to p do
begin
dp[x,i]:=dp[r[x],i];
for j:=0 to i-f[x] do
dp[x,i]:=max(dp[x,i],dp[l[x],j]+dp[r[x],i-j-f[x]]+w[x]);
end;
end;
begin
init;
tdp(root);
writeln(dp[root,p]);
close(input);
close(output);
end.
T4
题目描述:
从前有一条神奇的项链,为什么说它神奇呢?因为它有两个性质:
1. 神奇的项链可以拉成一条线,线上依次是N 个珠子,每个珠子有一个能量值Ei;
2. 除了第一个和最后一个珠子,其他珠子都满足Ei=(Ei-1+Ei+1)/2+Di。
由于这条项链很长,我们只能知道其两端珠子的能量值。并且我们知道每个珠子的Di是多少。请聪明的你求出这N 个珠子的能量值分别是多少。
代码:
var a,b,c,s:array[0..500000] of int64;
i,j,n,m:longint;
begin
assign(input,'fett.in');
assign(output,'fett.out');
reset(input);
rewrite(output);
read(n,a[1],a[n]); write(a[1],' ');
for i:=2 to n-1 do read(c[i]);
s[2]:=1; b[1]:=a[1];
for i:=3 to n do
begin
s[i]:=s[i-1]*2-s[i-2];
b[i]:=2*b[i-1]-b[i-2]-2*c[i-1];
end;
a[2]:=(a[n]-b[n]) div s[n];
write(a[2],' ');
for i:=3 to n do
begin
a[i]:=2*a[i-1]-a[i-2]-2*c[i-1];
write(a[i],' ');
end;
close(input);
close(output);
end.