2016.8.15C组模拟赛题解

12 篇文章 0 订阅
8 篇文章 0 订阅

这一套题怎么说呢,难的细节比较少,水的细节有点多,这第一题呢,计算加判断就行了,但是9个小时前的我,就因为打错了一个细节方面的问题(我是不会告诉你是怎么错),就与100分失之交臂,跌倒了0分的谷底,这就是差之毫厘失之千里!第二题很简单,DP直接过,比01背包还简单。第三题,呵呵,我用单源最短路径做,华丽丽地40分超时(人家对环合拓补排序还不懂嘛~~)第4题,我以为是DP,结果只是简单的BFS;

T1:Problem:某人总是花很多时间给父母打电话。有一次他记录了打电话的开始时间和结束时刻t1和t2,请你帮他算算此次通话一共用了多少秒。又有一次,他记录了打电话的开始时刻t1和通话的时间长度len,请你帮他计算他在什么时刻结束通话。
已知每次通话时间小于24个小时。

Input:输入文件phone.in的第一行为一个正整数T,表示了数据组数。 
接下来T行,每行第一个数为k:
如果k = 0,接下来包含两个时间t1和t2,表示了打电话的开始时间和结束时刻,用一个空格隔开,时间格式为HH:MM:SS,其中0≤HH≤23,0≤MM,SS≤59。HH、MM和SS都是两位数字,因此0:1:2是不合法的时间(应写作00:01:02)。你应该对这个询问输出通话时间长度,答案一定为区间[0,86400)之内的非负整数。
如果k=1,接下来包含一个时间t1和一个非负整数len,表示了打电话的开始时刻与通话时间长度,用一个空格隔开,时间格式同为HH:MM:SS,同样时间小于24个小时,即len<86400。你应该对这个询问输出结束通话的时刻,同为HH:MM:SS格式。

Output
输出文件phone.out包含T个整数或者时间,对于每个询问输出对应的答案。
样例:
input:4
                                          
0 01:02:03 04:05:06
0 23:59:59 00:00:00

1 00:00:03 3

1 23:59:58 4
output:10983

1

00:00:06

00:00:02
思路:很简单,看看是那种询问,在化为秒数,计算没判断(我的错在于len只有1位,答案错误get)
伪代码:
 readln(s);
                if s[1]='0' then
                begin
                        a:=(ord(s[3])-48)*10+ord(s[4])-48;
                        b:=(ord(s[6])-48)*10+ord(s[7])-48;
                        c:=(ord(s[9])-48)*10+ord(s[10])-48;
                        a1:=(ord(s[12])-48)*10+ord(s[13])-48;
                        b1:=(ord(s[15])-48)*10+ord(s[16])-48;
                        c1:=(ord(s[18])-48)*10+ord(s[19])-48;
                        x:=a*3600+b*60+c;
                        y:=a1*3600+b1*60+c1;
                        if y<x then y:=y+86400;
                        writeln(y-x);
                end;
                if s[1]='1' then
                begin
                        a:=(ord(s[3])-48)*10+ord(s[4])-48;
                        b:=(ord(s[6])-48)*10+ord(s[7])-48;
                        c:=(ord(s[9])-48)*10+ord(s[10])-48;
                        l:=length(s);
                        s1:=copy(s,12,l-12+1);
                        val(s1,y);
                        x:=(a*3600+b*60+c+y)mod 86400;
                        c:=x mod 60;
                        b:=(x div 60)mod 60;
                        a:=x div 3600;
                        if a<10 then write('0');
                        write(a,':');
                        if b<10 then write('0');
                        write(b,':');
                        if c<10 then write('0');
                        writeln(c);
                end;
T2:
problem:某地铁沿线共设N站,可分为U(地面式)、D(地下式)和C(复合式)三种类型。为避免单调,相邻地铁站的类型不能重复。同时,由于地铁站所处环境和地质条件有所差异,每个站点按不同类型的建设成本也不尽相同。现给定各站点的三种建设成本,请计算出该地铁线的最低总造价。
input:
3

1 99 99

99 1 99

99 99 1
output:
3
思路:很简单,跟01背包差不多,直接100分,设f[i,j]为在1到i站,i站为类型j的最小成本,方程式就是
  if (j<>k) then
                                        f[i,j]:=min(f[i,j],f[i-1,k]+a[i,j]);
伪代码:
     for i:=2 to n do
        begin
                for j:=1 to 3 do
                begin
                        for k:=1 to 3 do
                        begin
                                if (j<>k) then
                                        f[i,j]:=min(f[i,j],f[i-1,k]+a[i,j]);
                        end;
                end;
        end;
T3:

problem:X先生来到了一个奇怪的国家旅行。这个国家有N个城市,每个城市均有且仅有一个机场,但是这机场所有航班只飞往一个城市。每个城市有一个游览价值,第i个城市的游览价值为A[i]。
现在他想知道,从第i个城市出发,并只坐飞机飞往下一个城市,游览价值之和最多是多少(一个城市游览多次只计算1次游览价值)

input:

8

5 4 3 2 1 1 1 1

2 3 1 1 2 7 6 8
outpu t:

12

12

12

14

13

2

2

1
思路:比赛是我对每个i城市进行一次spfa,结果华丽丽超时,正解是拓补排序,先确认i城市在不在某个回路中,在根据在和不在的情况分别进行递归。

伪代码:

  bz1:=false;
        while not bz1 do
        begin
                bz1:=true;
                for i:=1 to n do
                begin
                        begin
                                if (father[i]=0)and(not hl[i]) then
                                begin
                                        hl[i]:=true;
                                        bz1:=false;
                                        dec(father[f[i]]);
                                end;
                        end;
                end;
        end;//判断在不在某回路
procedure find_1(x:longint);
begin
        bz[x]:=true;
        sum:=sum+a[x];
        if not bz[f[x]] then find_1(f[x]);
        vis[x]:=sum;
end;//在回路的情况
procedure find_2(x:longint);
begin
        bz[x]:=true;
        if not bz[f[x]] then find_2(f[x])
        else sum:=vis[f[x]];
        sum:=sum+a[x];
        vis[x]:=sum;
end;//不在回路的情况
T4:problem:小明完成了这样一个数字生成游戏,对于一个不包含0的数字s来说,有以下3种生成新的数的规则:
    1.将s的任意两位对换生成新的数字,例如143可以生成341,413,134;
    2.将s的任意一位删除生成新的数字,例如143可以生成14,13,43
    3.在s的相邻两位之间s[i],s[i + 1]之间插入一个数字x,x需要满足s[i]<x<s[i + 1],即比它插入位置两边的数小。例如143可以生成1243,1343,但是不能生成1143,1543等。
    现在小明想知道,在这个生成法则下,从s开始,每次生成一个数,可以用新生成的数生成另外一个数,不断生成直到生成t至少需要多少次生成操作。
    另外,小明给规则3又加了一个限制,即生成数的位数不能超过初始数s的位数。若s是143,那么1243与1343都是无法生成的;若s为1443,那么可以将s删除4变为143,再生成1243或1343。
 input:
 143
 3
 134
 133
 32
output
 1
 -1
 4
PS:143-》13-》123-》23-》32
	思路:bfs,在输入s后就开始预处理,按3种情况增加对列
伪代码:
    for i:=1 to l1-1 do
                begin
                        for j:=i+1 to l1 do
                        begin
                                str(d[head,1],s1);
                                ch:=s1[i];
                                s1[i]:=s1[j];
                                s1[j]:=ch;
                                val(s1,x);
                                if (s<>s1)and(bz[x]=0) then
                                begin
                                        tail:=tail mod 1000000+1;
                                        d[tail,1]:=x;
                                        d[tail,2]:=d[head,2]+1;
                                        bz[x]:=d[tail,2];
                                end;
                        end;
                end;//两两交换
  for i:=1 to l1 do
                begin
                        str(d[head,1],s1);
                        delete(s1,i,1);
                        val(s1,x);
                        if (s<>s1)and(bz[x]=0) then
                        begin
                                tail:=tail mod 1000000+1;
                                d[tail,1]:=x;
                                d[tail,2]:=d[head,2]+1;
                                bz[x]:=d[tail,2];
                        end;
                end;//删除其中一位
     str(d[head,1],s1);
                if l1<l then
                begin
                        for i:=1 to l1-1 do
                        begin
                                for j:=ord(s1[i])-47 to ord(s1[i+1])-49 do
                                begin
                                        if j=0 then continue;
                                        s2:=copy(s1,1,i)+chr(j+48)+copy(s1,i+1,l1-i);
                                        val(s2,x);
                                        if (s<>s2)and(bz[x]=0) then
                                        begin
                                                tail:=tail mod 1000000+1;
                                                d[tail,1]:=x;
                                                d[tail,2]:=d[head,2]+1;
                                                bz[x]:=d[tail,2];
                                        end;
                                end;
                        end;
                end;//插入j
然后就是读入并判断。
希望明天能更上一层楼,相信自己
希望这篇文章能对大家有帮助

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值