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,qq[55][55],b[MAXN],top[MAXN],q[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 next,y,v; 24 }e[MAXN*MAXN]; 25 void insert(int xx,int yy,int vv) 26 { 27 e[++len].next=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>>qq[i][j]; 40 } 41 void spfa() 42 { 43 memset(dis,10,sizeof(dis)); 44 int head=0,tail=1; dis[S]=0; book[S]=1; q[1]=S; 45 while(++head<=tail){ 46 int x=q[head]; 47 for(int i=Link[x];i;i=e[i].next){ 48 if(dis[x]+e[i].v<dis[e[i].y]){ 49 dis[e[i].y]=dis[x]+e[i].v; 50 if(!book[e[i].y]){ 51 q[++tail]=e[i].y; 52 book[e[i].y]=1; 53 } 54 } 55 } 56 book[x]=0; 57 } 58 } 59 void work() 60 { 61 for(int i=1;i<=n;i++) 62 for(int j=1;j<=n;j++) 63 { 64 int t=qq[i][j]; 65 stack[t][++top[t]]=(i-1)*n+j; 66 for(int k=0;k<4;k++) 67 { 68 int tx=i+dx[k],ty=j+dy[k]; 69 if(tx<=0||ty<=0||tx>n||ty>n) continue; 70 insert((i-1)*n+j,(tx-1)*n+ty,b[qq[tx][ty]]); 71 insert((tx-1)*n+ty,(i-1)*n+j,b[qq[i][j]]); 72 } 73 for(int k=1;k<top[t];k++) 74 { 75 insert((i-1)*n+j,stack[t][k],0); 76 insert(stack[t][k],(i-1)*n+j,0); 77 } 78 } 79 T=n*n+1; 80 for(int i=1;i<=n;i++) 81 { insert(S,i,b[qq[1][i]]); 82 insert((n-1)*n+i,T,0); 83 } 84 spfa(); 85 if(h<=dis[T]) cout<<"NO"<<endl; 86 else cout<<h-dis[T]<<endl; 87 } 88 int main() 89 { 90 //freopen(FILE".in","r",stdin); 91 //freopen(FILE".out","w",stdout); 92 init(); 93 work(); 94 return 0; 95 }
(这大概也许能过吧.....)
(祈祷)我以后绝对好好写题,我以后再也不学什么另类奇葩算法的另一种形式了,我以后绝对只写一种格式,我以后再也不看题解啦,我以后每道题都好好写,我以后每道题都写题解。
再也不浪啦~
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?
不错啦