题目名称

rabbits

cubes

bags

输入文件

Frog.in

Cubes.in

Bags.in

输出文件

Frog.out

Cubes.out

Bags.out

测试点数目

10

10

10

测试点分数

10

10

10

时间限制

1s

1s

1s

空间限制

128M

128M

128M

将水题进行到底

——第三阶段模拟五day1

任何名称均小写。

The rabbits

【题目描述】

众所周知,除了青蛙会跳之外,兔纸也会。

在一片n*m的菜地中,有一些兔纸在活动,每只兔纸可以在菜地中跳来跳去。但是有一些限制条件:

兔纸只能从菜地外跳进菜地内,并且最后一定要跳出去,每只兔纸跳的每步都是等方向、等长的;兔纸在菜地内至少踩到三个点。

这样每只兔纸就在菜地里留下了一条路径。现在告诉你菜地中那些被兔纸踩过(一个点可能被踩不止一次),某人决定捉住一只踩坏菜地块数最多的兔纸惩罚他,来杀一儆百。

【输入格式】

第一行两个整数n,m(1<=n,m<=5000)

第二行一个整数q被踩的点的个数(3<=q<=5000);

接下来q行每行表示被踩点的横纵坐标。

【输出格式】

踩坏菜地最多的兔纸踩坏的菜地数。

【输入样例】

6 7

14

2 1

6 6

4 2

2 5

2 6

2 7

3 4

6 1

6 2

2 3

6 3

6 4

6 5

6 7

【输出样例】

7

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n,m,q;
struct node{
       int x,y;
       friend bool operator <(node a,node b){
              if (a.x!=b.x) return a.x>b.x;
              else return a.y>b.y;
       }
}a[510000];
int map[5010][5010];
int ans=2,now;

void make(int x,int y,int xx,int yy){
     now=2;
     while (x+xx>0 && x+xx<=m && y+yy>0 && y+yy<=n){
           if (map[x+xx][y+yy]){
                                x+=xx;
                                y+=yy;
                                ++now;
           }else {now=0;return;}
     }
}

int main(){
    freopen("frog.in","r",stdin);
    freopen("frog.out","w",stdout);
    scanf("%d%d%d",&m,&n,&q);
    for (int i=1;i<=q;i++){
        scanf("%d%d",&a[i].x,&a[i].y);
        map[a[i].x][a[i].y]=1;
    }
    sort(a+1,a+1+q);
    for (int i=1;i<=q;i++){
        for (int j=i+1;j<=q;j++){
            int x=a[j].x-a[i].x;
            int y=a[j].y-a[i].y;
            if (a[i].x-x>m || a[i].x-x<=0 || a[i].y-y>n || a[i].y-y<=0)
                           if (y*(ans-1)+a[i].y<=n && y*(ans-1)+a[i].y>0) make(a[j].x,a[j].y,x,y);
            if (now>ans) ans=now;
        }
    }
    if (ans==2) printf("0\n");else printf("%d\n",ans);
    return 0;
}

 

The cubes

【题目描述】

lynn 和 banana 用 N (1 <= N <= 30,000)块相同的小立方块玩游戏,小方块编号为 1..N。开始时,小方块都单独分开的,每个看成一个柱子,即有 N 柱子。lynn 要 banana 做 P(1 <= P <= 100,000) 个操作,操作有两种类型:
(1) lynn 要求banana 把X 号方块所在的柱子放到 Y 号所在的柱子上面,成一个新柱子。
(2) lynn 要求 banana 计算X 号方块所在柱子,它下面有多少个小方块。
请编个程序,帮助 lynn 计算。

【输入格式】
*第一行:一个整数 P
*第 2..P+1 行:第 i+1 行表示第 i 个 FJ 要求的合法操作。如果这行以'M'开头,后面有两个整
数 X,y 表示要进入(1)操作。 如果这行以'C'开头,后面有一个整数 X,表示要求计算 X 所在
柱子下面的方块个数。
注:所有操作都是合法的。N 并没有出现在输入文件中。

【输出格式】
依次要求计算的值,每次一行。
【输入样例】
6 | 6 个操作
M 1 6
| 1,6 / 2 / 3 / 4 / 5 把 1 放在 6 上面。
C 1
| 输出:1
M 2 4
| 1,6 / 2,4 / 3 / 5
M 2 6
| 2,4,1,6 / 3 / 5
C 3
| 输出 :0
C 4
| 输出: 2

【输出样例】
1
0
2

 

//by_Spray_2011_11_02_9:10 Union_Findset
program __cube;
var
  fa,size,before:array[0..31000] of longint;
  n,i,x,y,a,b:longint;
  c:char;

function get(x:longint):longint;
  var
    t:longint;
  begin
    if (fa[x]=x) then exit(x);
    t:=get(fa[x]);
    inc(before[x],before[fa[x]]);
    fa[x]:=t;
    exit(fa[x]);
  end;
begin
  assign(input,'cubes.in');
  reset(input);
  assign(output,'cubes.out');
  rewrite(output);
  readln(n);
  for i:=1 to 30000 do
    begin
      fa[i]:=i;
      size[i]:=1;
      before[i]:=0;
    end;
  for i:=1 to n do
    begin
      read(c);
      if (c='M') then
        begin
          readln(a,b);
          x:=get(a);
          y:=get(b);
          if (x<>y) then
            begin
              fa[x]:=y;
              before[x]:=size[y];
              inc(size[y],size[x]);
              size[x]:=0;
            end;
        end
      else
        begin
          readln(a);
          x:=get(a);
          writeln(before[a]-before[x]);
        end;
    end;
  close(input);
  close(output);
end.

 

The bags

【题目描述】

Lynn 和banana要去爬山啦!他们一共有 K 个人(banana的人数可以看作很多),每个人都会背一个包。这些包的容量是相同的,都是 V。可以装进背包里的一共有 N 种物品,每种物品都有给定的体积和价值。在 lynn看来,合理的背包安排方案是这样的:
(1)每个人背包里装的物品的总体积恰等于包的容量。
(2)每个包里的每种物品最多只有一件,但两个不同的包中可以存在相同的物品。
(3)任意两个人,他们包里的物品清单不能完全相同。
在满足以上要求的前提下,所有包里的所有物品的总价值最大是多少呢?

【输入格式】

第一行有三个整数:K、V、N。(k<=50 v<=5000 n<=200)第二行开始的 N 行,每行有两个整数,分别代表这件物品的体积和价值。
【输出格式】

只需输出一个整数,即在满足以上要求的前提下所有物品的总价值的最大值。(最后有空行.)
【样例输入】
2 10 5
3 12
7 20
2 4
5 6
1 1
【样例输出】
57

//by_Spray_2011_11_02 The Kth bag
program __bags;
var
  k,maxv,n,z:longint;
  p,q:array[0..5000] of longint;
  i,j,a,b,ans:longint;
  f:array[0..6000,0..60] of longint;
  w,s:array[0..300] of longint;

begin
  assign(input,'bags.in');
  reset(input);
  assign(output,'bags.out');
  rewrite(output);
  readln(k,maxv,n);
  for i:=1 to n do
    readln(w[i],s[i]);
  fillchar(f,sizeof(f),200);
  f[0][1]:=0;
  for i:=1 to n do
    for j:=maxv downto w[i] do
      begin
        for z:=1 to k do
          begin
            p[z]:=f[j][z];
            q[z]:=f[j-w[i]][z]+s[i];
          end;
        a:=1;
        b:=1;
        for z:=1 to k do
          begin
            if (p[a]>q[b]) then
              begin
                f[j][z]:=p[a];
                inc(a);
              end
              else
              begin
                f[j][z]:=q[b];
                inc(b);
              end;
          end;
      end;
  for i:=1 to k do
    inc(ans,f[maxv][i]);
  writeln(ans);
  close(input);
  close(output);
end.

 

 

Day2

文件名

Mobiles

Bobsled

car

输入文件

Mobiles.in

Bobsled.in

Car.in

输出文件

Mobiles.out

Bobsled.out

Car.out

将水题进行到底(2)

时间限制一律1s,内存限制一律128M.

前奏:

话说maxingc终于知道了为什么小菜菜和寒英的儿子分别叫窄森和暖熊了,张涛的想象力还真丰富啊……

这一天菜菜和寒英要出远门,将他们的儿子交给了maxingc照顾,作为菜菜和寒英的好朋友,maxingc当然要好好玩玩窄森和暖熊了,啊不,是带他们好好玩玩了……

Maxingc从商店买回来了好多玩具啊!有风铃,赛车,大富翁……

No.1风铃

风铃是一种多层的装饰品,一般挂在天花板上。每个风铃都包含一些由竖直的线连起来的水平杆。每根杆的两端都有线连接,下面或者挂着另一根水平杆,或者挂着一个玩具。下面是一个风铃的例子:

clip_image001

但是maxingc是一个完美主义者(说到完美主义者,还真是恐怖啊,柯南剧场版的前两部凶手都是完美主义者啊),他对风铃的要求如下:

(1) 所有的玩具都在同一层(也就是说,每个玩具到天花板之间的杆的个数是一样的)或至多相差一层。

(2) 对于两个相差一层的玩具,左边的玩具比右边的玩具要更靠下一点。

 风铃可以按照下面的规则重新排列:任选一根杆,将杆两端的线“交换”。也就是解开一根杆左右两端的线,然后将它们分别绑到杆的另一端。注意这个操作不会改变下面的杆上线的排列顺序。

Maxingc给窄森一个风铃,让他在1s中之内将它调整到所要求的样子,否则就不让他吃午饭,可怜的窄森怎么会在1s内完成,所以要求助于学oi的你。你只需在一秒钟内说出最少需要几次交换就行了。

考虑上面的例子,上图中得风铃满足条件1,却不满足条件2。

但是,我们可以通过下面的步骤把这个风铃变成一个符合要求的。

clip_image003

Input

  输入的第一行包含一个整数n (1 ≤ n ≤ 100000),表示风铃中有多少根杆。接下来的n行描述杆的连接信息。这部分的第i行包含两个由空格分隔的整数li和ri,描述杆i的左右两端悬挂的东西。如果挂的是一个玩具,则对应的值为-1,否则为挂在下面的杆的编号。如果杆i下面挂有其它杆,则这些杆的编号将严格大于i。杆1位于风铃的顶部。

Output

  输出仅包含一个整数。表示最少需要多少次交换能使风铃满足Ike的条件。如果不可能满足,输出-1。

Sample Input

6 2

2 3

-1 4

5 6

-1 -1

-1 -1

-1 -1

Sample Output

2

 

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

int n;
int son[110000][3];
int into[110000];
int num[110000];
int root;
int maxlen,minlen=0x7fffffff;
int ans;
int tot,tot2;

void getlen(int x,int d){
     if (x==-1){
                if (d<minlen) minlen=d;
                if (d>maxlen) maxlen=d;
                return;
     }
     getlen(son[x][0],d+1);
     getlen(son[x][1],d+1);
}

void getnum(int x){
     if (x==-1) return;
     num[x]=1;
     getnum(son[x][0]);
     getnum(son[x][1]);
     num[x]+=num[son[x][0]]+num[son[x][1]];
}

void getans(int x){
     if (x==-1) return;
     if (son[x][0]!=-1 && son[x][1]!=-1){
                        getans(son[x][1]);
                        getans(son[x][0]);
     }
     if ((son[x][0]==-1 && son[x][1]!=-1) || (son[x][0]!=-1 && son[x][1]==-1)) tot++;
     if ((num[son[x][0]]==1 && num[son[x][1]]>1) || (num[son[x][0]]>1 && num[son[x][1]]==1)) tot2++;
     if (num[son[x][1]]>num[son[x][0]]) ans++;
}

int main(){
    freopen("mobiles.in","r",stdin);
    freopen("mobiles.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
        scanf("%d%d",&son[i][0],&son[i][1]);
        into[son[i][0]]++;
        into[son[i][1]]++;
    }
    for (int i=1;i<=n;i++){
        if (!into[i]) {root=i;break;}
    }
    getlen(root,0);
    if (maxlen-minlen>1){
                         printf("-1\n");
                         return 0;
    }
    getnum(root);
    getans(root);
    if (tot>1 || tot2>1){
               printf("-1\n");
               return 0;
    }
    printf("%d\n",ans);
    return 0;
}

 

No.2赛车

Maxingc不仅为暖熊买来了赛车,还为他买来了赛道,赛道的长度为L(2<=L<=10^9)m。赛车在起点的速度是1m/s,但是赛车的速度是可以改变的,每一米的速度可以是前一秒的速度加1,减1或不变。赛道有n(1<=n<=100000)个转弯处,第i个转弯处位于距离出发点Ti(1<=Ti<=L-1)米处,为了安全起见,赛车到达第i个转弯处的速度不能超过Si(1<=Si<=10^9)米每秒,当然赛车到达终点时的速度没有最大的限度。

Maxingc让暖熊1秒内计算出赛车能达到的最大的速度是多少,否则就不让他吃晚饭。

这这这……为了暖熊的人身安全,还是请教你吧!

输入格式:

第一行:两个正整数L,N。

第二行到第N+1行:第i+1行描述的是第i个转弯处的两个参数Ti,Si。

输出格式:

一个整数,表示赛车能达到的最大速度(包括起点和终点的速度)。

输入样例:

14 3

7 3

11 1

13 8

输出样例:

5

样例说明:

限速

             

3

     

1

 

8

 

距离

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

速度

1

2

3

4

5

5

4

3

4

3

2

1

2

3

4

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int L,N;
struct node{
       int T,S;
}a[100010];
int ans;

int cmp(const node &a,const node &b){return a.T<b.T;}

int main(){
    freopen("bobsled.in","r",stdin);
    freopen("bobsled.out","w",stdout);
    scanf("%d%d",&L,&N);
    for (int i=1;i<=N;i++){
        scanf("%d%d",&a[i].T,&a[i].S);
    }
    a[0].T=0;
    a[0].S=1;
    sort(a,a+1+N,cmp);
    a[N+1].T=L;
    a[N+1].S=a[N+1].T-a[N].T+a[N].S;
    for (int i=1;i<=N+1;i++){
        if (a[i].S>a[i-1].S)
        if (a[i].S>a[i].T-a[i-1].T+a[i-1].S){
                                    a[i].S=a[i].T-a[i-1].T+a[i-1].S;
        }
    }
    for (int i=N+1;i>0;i--){
        if (a[i].S<a[i-1].S)
        if (a[i-1].S-a[i].S>a[i-1].T-a[i].T) a[i-1].S=a[i].T-a[i-1].T+a[i].S;
    }
    for (int i=1;i<=N+1;i++){
        if (a[i].S>a[i-1].S)
        if (a[i].S>a[i].T-a[i-1].T+a[i-1].S){
                                    a[i].S=a[i].T-a[i-1].T+a[i-1].S;
        }
    }
    for (int i=0;i<=N;i++){
        if (a[i].S<a[i+1].S){
                             int Ma=a[i+1].S;
                             int t=a[i+1].T-a[i].T;
                             t-=a[i+1].S-a[i].S;
                             if (t>0) --t;
                             if (t & 1) Ma+=t/2+1;else Ma+=t/2;
                             if (Ma>ans) ans=Ma;
        }else{
              int Ma=a[i].S;
              int t=a[i+1].T-a[i].T;
              t-=a[i].S-a[i+1].S;
              if (t>0) --t;
              if (t & 1) Ma+=t/2+1;else Ma+=t/2;
              if (Ma>ans) ans=Ma;
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

No.3 大富翁

Maxingc买来的大富翁游戏规则有些不一样。

这是一个N*N 的方形网格,设其左上角为起点◎,坐标为(1,1),X 轴向右为正,Y

轴向下为正,每个方格边长为1,如图所示。一辆汽车从起点◎出发驶向右下角终点▲,其

坐标为(N,N)。在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油。汽车在

行驶过程中应遵守如下规则:

(1)汽车只能沿网格边行驶,装满油后能行驶K 条网格边。出发时汽车已装满油,在起

点与终点处不设油库。

(2)汽车经过一条网格边时,若其X 坐标或Y 坐标减小,则应付费用B,否则免付费用。

(3)汽车在行驶过程中遇油库则应加满油并付加油费用A。

(4)在需要时可在网格点处增设油库,并付增设油库费用C(不含加油费用A)。

(5)(1)~(4)中的各数N、K、A、B、C均为正整数,且满足约束:2 <=n<=100,2<=k<=10;

clip_image005

Maxingc让窄森和暖熊在1s的时间内求出从起点到终点最少的花费。否则就不让他们今天晚上睡觉。Hzoiers,帮帮这些孩子吧!

输入格式:

文件的第一行是N,K,A,B,C的值。第二行起是一个N*N 的0-1 方阵,每行N 个值,至N+1 行结束。方阵的第i 行第j 列处的值为1 表示在网格交叉点(i,j)处设置了一个油库,为0 时表示未设油库。各行相邻两个数以空格分隔。

  输出格式:

最小费用。

  输入样例:

9 3 2 3 6

0 0 0 0 1 0 0 0 0

0 0 0 1 0 1 1 0 0

1 0 1 0 0 0 0 1 0

0 0 0 0 0 1 0 0 1

1 0 0 1 0 0 1 0 0

0 1 0 0 0 0 0 1 0

0 0 0 0 1 0 0 0 1

1 0 0 1 0 0 0 1 0

0 1 0 0 0 0 0 0 0

输出样例:

12

还好还好,明天菜菜和寒英就会回来了,要是再多几天,估计他们儿子的性命就难保了……

 

 

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

#define MAXQ 1000000

int di[4]={0,1,0,-1};
int dj[4]={1,0,-1,0};
int N,K,A,B,C;
int map[110][110];
int d[110][110][110];
int v[110][110][110];
struct node{
	int x,y,gas;
}f[1000010];
int ans=0x7fffffff;

void SPFA(){
	memset(d,63,sizeof(d));
	d[1][1][K]=0;
	int head=0,tail=1;
	f[tail].x=1;
	f[tail].y=1;
	f[tail].gas=K;
	v[1][1][K]=1;
	while (head!=tail){
		head++;
		if (head==MAXQ) head=1;
		int x=f[head].x;
		int y=f[head].y;
		int t=f[head].gas;
		v[x][y][t]=0;
		for (int s=0;s<4;s++){
			int tx=x+di[s];
			int ty=y+dj[s];
			if (tx>0 && ty>0 && tx<=N && ty<=N){
				int cos=d[x][y][t]+A*map[x][y]+((tx>=x && ty>=y)?0:B);
				int ga=f[head].gas;
				if (map[x][y]) ga=K;
				if (!map[x][y] && !ga) {cos+=A+C;ga=K;}
				
				if (tx==N && ty==N){
					if (cos<ans) ans=cos;
				}
				if (d[tx][ty][ga-1]>cos){
                    d[tx][ty][ga-1]=cos;
                    if (!v[tx][ty][ga-1]){
                                          tail++;
					                      if (tail==MAXQ) tail=1;
					                      f[tail].x=tx;
					                      f[tail].y=ty;
					                      f[tail].gas=ga-1;
					                      v[tx][ty][ga-1]=1;
                    }
				}
			}
		}
	}
}

int main(){
	freopen("car.in","r",stdin);
	freopen("car.out","w",stdout);
	cin>>N>>K>>A>>B>>C;
	for (int i=1;i<=N;i++){
		for (int j=1;j<=N;j++){
			scanf("%d",&map[i][j]);
		}
	}
	SPFA();
	cout<<ans<<endl;
	return 0;
}