首页 > 代码库 > Test on 11/15/2016

Test on 11/15/2016

@kaike

1.还是字符串

  (string.pas/c/cpp)

【问题描述】

给定一个长度为n的字符串,其中只包含小写字母a,b

你要将一些b改成a,使其中的任意连续k个字符至少包含q个a

你要计算出最小修改次数。

【输入】

第一行三个正整数n,k,q

第二行一个长度为n的字符串。

【输出】

一行一个正整数,表示最少改变的数量。

【输入输出样例1】

string.in

string.out

10 6 5

ababbaabbb

4

 

【数据范围】

   数据范围:

30% n,k,q<=500

40% n,k,q<=5000

50% n,k,q<=10000

60% n,k,q<=100000

另20% n<=100000 k,q<=100

100%   n,k,q<=1000000

 

知道队列知道替换,可是不会写....

也知道后面换的优先...

技术分享
 1 /*
 2 by kaike
 3 11/15/2016
 4 */
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<cstdio>
 8 #include<ctime>
 9 #include<cstring>
10 #include<string>
11 #include<cmath>
12 #include<queue>
13 #include<iomanip>
14 using namespace std;
15 const int MAXN=1001000;
16 #define FILE "string"
17 int que[MAXN],a[MAXN],ans=0,head=0,tail=0,sumb=0,datab=0;
18 char s;
19 int n,k,q;
20 void work()
21 {
22     cin>>n>>k>>q;
23     for(int i=1;i<=n;i++)
24     {
25         cin>>s;
26         que[++tail]=s;
27         if(que[tail]==b)  {sumb++;    datab=tail;}
28         if(tail-head==k)
29         {
30             if(sumb>k-q)
31             {
32                 for(int i=datab;i>head;i--)
33                 {
34                     if(sumb<=k-q)   break;
35                     if(que[i]==b)
36                     {
37                         que[i]=a;
38                         sumb--;
39                         ans++;
40                     }
41                 }
42             }
43             if(que[++head]==b)    sumb--;
44         }
45     }
46     cout<<ans<<endl;
47 }
48 int main()
49 {
50     //freopen(FILE".in","r",stdin);
51     //freopen(FILE".out","w",stdout);
52     work();
53     return 0;
54 }
= =

 

1.探险

  (risk.pas/c/cpp)

【问题描述】

    探险和迷宫是OI考试永恒的主题。

    现在小x又一次要冒险了。不过这次是一个魔法结界。

这些魔法结界根据种类的不同分为N种,踏入每种结界,小x都会受到一定的伤害。为了拿到宝藏,这些伤害是必须要承受的。但是小x要尽可能地减少伤害,请你设计一条路线,使小x通过结界获取宝藏受到的伤害最少。

下面是一个魔法结界能量示意图,结界是一个正方形,内部有P种不同的能量,每种能量由不同的数字表示。小x从最上端开始走,每次可以走到与你所在的位置上下左右相邻的临位,或者在同种能量结界中任意传送重复进入同一种能量结界不会再次受到伤害

|111223|

|123333|

|112244|

|555556|

|577566|

|776666|

小x有H点生命值,请你在贸然行动之前先判断是否能够活着(生命值大于0)穿越结界拿到宝藏,如果能够,请求出最多剩余的生命值。

【输入】

第1行 三个非负整数 N,P,H。N为结界的边长,P为不同的能量结界的数量,H为你的生命值。

第2-P+1行 每行一个非负整数,表示走到该种能量结界受到的伤害值。

第P+2至第P+2+N行 每行N个正整数,为地图上该单元格的能量种类的编号,编号为1..P。

【输出】

如果小x能够通过结界到达对岸的宝藏,输出最多剩余的生命值。

如果不能通过,输出NO。

 

【输入输出样例1】

risk.in

risk.out

6 7 10

3

1

2

2

1

1

3

1 1 1 2 2 3

1 2 3 3 3 3

1 1 2 2 4 4

5 5 5 5 5 6

5 7 7 5 6 6

7 7 6 6 6 6

7

 

 

【样例说明】

 

路线为

起始-2-5-6-目标

1 1 1 2 2 3

1 2 3 3 3 3

1 1 2 2 4 4

5 5 5 5 5 6

5 7 7 5 6 6

7 7 6 6 6 6

 

【数据范围】

 对于40%数据   4<=N<=10

对于100%数据  4<=N<=50;  1<=P<=N*N;  0<=H<=200000000

 

不是很懂dfs的弱渣写了dfs

然而写崩了

正解居然是图!!

根本没有想到好嘛

最重要的是建图。

把每个点都枚举一遍,把坐标存成一个一个的点(i-1)*n+j

然后上下左右走,遇到一个点连接一条边,然后相同的也连接一条边,权值为0

然后加入一个S=0,T=n*n+1,把第一行的点与S相连,最后一行的点与T相连。

技术分享
 1 /*
 2 by kaike
 3 11/15/2016
 4 */
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<cstring>
 8 #include<string>
 9 #include<ctime>
10 #include<cmath>
11 #include<iomanip>
12 #include<cstdio>
13 using namespace std;
14 #define FILE "risk"
15 const int MAXN=2510;
16 int book[MAXN],dis[MAXN],Link[MAXN],len=0;
17 int n,p,h,map[55][55],b[MAXN],top[MAXN];
18 int stack[MAXN][MAXN],S,T;
19 int dx[5]={0,0,-1,1};
20 int dy[5]={1,-1,0,0};
21 struct qaq
22 {
23     int x,y,v;
24 }e[MAXN*MAXN];
25 void insert(int xx,int yy,int vv)
26 {
27     e[++len].x=Link[xx];
28     Link[xx]=len;
29     e[len].y=yy;
30     e[len].v=vv;
31 }
32 void init()
33 {
34     cin>>n>>p>>h;
35     for(int i=1;i<=p;i++)
36         cin>>b[i];
37     for(int i=1;i<=n;i++)
38         for(int j=1;j<=n;j++)
39             cin>>map[i][j];
40 }
41 void spfa(int x)
42 {
43     book[x]=1;
44     for(int i=Link[x];i;i=e[i].y)
45     {
46         if(e[i].v+dis[x]<dis[e[i].y])
47         {
48             dis[e[i].y]=dis[x]+e[i].v;
49             spfa(e[i].y);
50         }
51     }
52     book[x]=0;
53 }
54 void work()
55 {
56     for(int i=1;i<=n;i++)
57         for(int j=1;j<=n;j++)
58         {
59             int t=map[i][j];
60             stack[t][++top[t]]=(i-1)*n+j;
61             for(int k=0;k<4;k++)
62             {
63                 int tx=i+dx[k],ty=j+dy[k];
64                 if(tx<=0||ty<=0||tx>n||ty>n)    continue;
65                 insert((i-1)*n+j,(tx-1)*n+ty,b[map[tx][ty]]);
66                 insert((tx-1)*n+ty,(i-1)*n+j,b[map[i][j]]);
67             }
68             for(int k=1;k<top[t];k++)
69             {
70                 insert((i-1)*n+j,stack[t][k],0);
71                 insert(stack[t][k],(i-1)*n+j,0);
72             }
73         }
74     T=n*n+1;    S=0;   
75     for(int i=1;i<=n;i++)
76     {   insert(S,i,b[map[1][i]]);
77         insert((n-1)*n+i,T,b[map[n][i]]);
78     }
79     memset(dis,10,sizeof(dis));
80     spfa(S);
81     if(h<=dis[T])   cout<<"NO"<<endl;
82     else    cout<<h-dis[T]<<endl;
83 }
84 int main()
85 {
86     //freopen(FILE".in","r",stdin);
87     //freopen(FILE".out","w",stdout);
88     init();
89     work(); 
90     return 0;
91 }
= =

(这大概也许能过吧.....)

 

1.二维线段覆盖

  (line.pas/c/cpp)

【问题描述】

平面上有N个线段,其中每一个线段的坐标都为整数且都平行坐标轴,请统计线段总覆盖的整数点的个数。

假设每一个点的坐标为x[i],y[i]。

【输入】

第一行

一个正整数n,表示一共有n个线段。

接下来n行,每一行4个整数,表示起始坐标x[i],y[i]和终点坐标xx[i]和yy[i]表示n个平行于坐标轴的线段的起始坐标和终点坐标。

【输出】

一行一个整数,表示线段一共覆盖坐标整点的个数

【输入输出样例1】

line.in

line.out

4

0 1 3 1

0 2 3 2

1 0 1 3

2 0 2 3

12

 

【输入输出样例2】

line.in

line.out

3

0 1 3 1

1 1 4 1

7 7 7 7

6

 

【数据范围】

数据编号

n

坐标范围

特殊

时间

1

<=10

<=100

 

2s

2

<=1000

<=5000

 

3

<=10^6

 

4

<=10^8

 

5

<=5000

<=1000

 

6

<=5000

 

7

<=10^6

 

8

<=10^8

 

9

<=100000

<=1000

 

10

<=5000

 

11

<=10^6

 

12

<=10^8

所有线段长度<=10

13

不存在平行于X轴的线段

14

平行于X轴的线段最多100个

15

任意平行于同一坐标轴的线段不会重合

16

 

17

<=300000

<=10^8

 

4s

18

<=500000

 

19

<=700000

 

20

<=1000000

 

 

子祯大神十分严谨,然而....该放弃咯

用二维布尔可以拿到25-30?

不错啦

 

Test on 11/15/2016