题目链接:http://vjudge.net/contest/142053#overview
A.题意:有一个3*n的隧道,人和车轮流走,人先向右走一步,然后选在是在原地不动还是上下移动一格,之后车开始往左移两格,问人是否能走到隧道尽头
思路:车是不会上下动的,那么我们按照相对来算就行,也就是人相当于往右走一步,然后选择不动还是上下移动一格,然后往右走两步。bfs处理把能走到的点加入到队列
bfs和dp其实思路是一样的,都是从左到右递推过去的
1 #include <stdio.h> 2 #include <iostream> 3 #include <algorithm> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <queue> 7 using namespace std; 8 char G[4][110]; 9 bool flag[4][110]; 10 int n; 11 bool vis; 12 struct node{ 13 int x,y; 14 }; 15 bool judge(int x,int y){ 16 return G[x][y]=='.'; 17 } 18 bool ok(node &temp){ 19 if(judge(temp.x,temp.y)){ 20 if(judge(temp.x,temp.y+1)){ 21 if(temp.y+1==n) vis=true; 22 } 23 if(judge(temp.x,temp.y+1)&&judge(temp.x,temp.y+2)){ 24 if(temp.y+1==n||temp.y+2==n) vis=true; 25 } 26 if(judge(temp.x,temp.y+1)&&judge(temp.x,temp.y+2)){ 27 temp.y+=2; 28 if(!flag[temp.x][temp.y]){ 29 return true; 30 } 31 } 32 } 33 return false; 34 } 35 bool bfs(int posx,int posy){ 36 memset(flag,false,sizeof(flag)); 37 queue<node> q; 38 vis=false; 39 while(!q.empty()) q.pop(); 40 node e; 41 e.x=posx,e.y=posy; 42 q.push(e); 43 flag[e.x][e.y]=true; 44 while(!q.empty()){ 45 node tmp=q.front(); 46 q.pop(); 47 if(tmp.y==n) return true; 48 else { 49 node temp,tmpup,tmpdown; 50 temp=tmp; 51 temp.y=tmp.y+1; 52 if(!judge(temp.x,temp.y)) continue; 53 if(temp.y==n) return true; 54 tmpup=temp,tmpup.x+=1; 55 tmpdown=temp,tmpdown.x-=1; 56 if(ok(temp)){ 57 q.push(temp); 58 flag[temp.x][temp.y]=true; 59 } 60 if(ok(tmpup)){ 61 q.push(tmpup); 62 flag[tmpup.x][tmpup.y]=true; 63 } 64 if(ok(tmpdown)){ 65 q.push(tmpdown); 66 flag[tmpdown.x][tmpdown.y]=true; 67 } 68 if(vis) return true; 69 } 70 } 71 return false; 72 } 73 void solve(int T){ 74 int k; 75 scanf("%d %d",&n,&k); 76 int x,y; 77 for(int i=1;i<=3;i++){ 78 for(int j=1;j<=n;j++){ 79 scanf(" %c",&G[i][j]); 80 if(G[i][j]=='s') { 81 x=i,y=j; 82 } 83 } 84 } 85 if(bfs(x,y)){ 86 printf("YES "); 87 } 88 else 89 printf("NO "); 90 return ; 91 } 92 int main(){ 93 int T; 94 while(scanf("%d",&T)!=EOF){ 95 for(int i=1;i<=T;i++) solve(i); 96 } 97 }
B.题意:有一个字符串,看能不能在字符串的任意位置插入一个字符串使得这个字符串是回文串
思路:水题,暴力插入
1 #include <stdio.h> 2 #include <iostream> 3 #include <algorithm> 4 #include <string.h> 5 using namespace std; 6 char str[20]; 7 char tmp[20]; 8 bool judge(int len){ 9 for(int i=0;i<=len;i++){ 10 if(tmp[i]!=tmp[len-i]){ 11 return false; 12 } 13 } 14 return true; 15 } 16 void solve(){ 17 int len=strlen(str); 18 for(int i=0;i<=len;i++){ 19 for(int j=0;j<26;j++){ 20 tmp[i]='a'+j; 21 for(int k=0;k<i;k++) tmp[k]=str[k]; 22 for(int k=i+1;k<=len;k++) tmp[k]=str[k-1]; 23 if(judge(len)){ 24 for(int k=0;k<=len;k++){ 25 printf("%c",tmp[k]); 26 } 27 printf(" "); 28 return ; 29 } 30 } 31 } 32 printf("NA "); 33 return ; 34 } 35 int main(){ 36 while(scanf("%s",str)!=EOF){ 37 solve(); 38 } 39 return 0; 40 }
D.题意:有一个n*n的棋盘,白棋在(1,1),黑棋(1,n),其余的地方都是绿棋子,棋子的走法和国际象棋里面的皇后一样,白棋和黑棋走的路上必须吃子
当某个棋子不能吃子或者被对手吃了就算输了,输出谁输,如果白棋赢输出白棋走的第一步,l和c都尽量小
思路:如果棋盘是奇数的话,白棋先手,黑棋走白棋的镜像,这样的话相当于当白棋走到中间时,黑棋总能把它吃掉。
如果棋盘是偶数的话,白棋先手走(1,2)这样相当于把棋盘变成奇数并且黑棋先手了,那样黑棋必输,而白棋总能通过先走(1,2)来赢
1 #include <stdio.h> 2 int main(){ 3 int n; 4 while(scanf("%d",&n)!=EOF){ 5 if(n&1)printf("black "); 6 else { 7 printf("white 1 2 "); 8 } 9 } 10 return 0; 11 }
F:题意:有很多个约束条件,输出满足约束条件的任意一个数
思路:设一个l,r表示上界和下界,不断夹就行,矛盾就不行(代码有点丑QwQ)
1 #include <stdio.h> 2 #include <iostream> 3 #include <algorithm> 4 #include <string.h> 5 using namespace std; 6 char str[5]; 7 int num; 8 char type[5]; 9 void solve(int T){ 10 int l=-2e9; 11 int r=2e9; 12 bool flag=true; 13 while(T--){ 14 scanf("%s%d%s",str,&num,type); 15 if(type[0]=='N'){ 16 if(str[0]=='>'){ 17 if(str[1]=='='){ 18 if(num-1<l){ 19 flag=false; 20 continue; 21 } 22 r=min(r,num-1); 23 } 24 else { 25 if(num<l) { 26 flag=false; 27 continue; 28 } 29 r=min(r,num); 30 } 31 } 32 if(str[0]=='<'){ 33 if(str[1]=='='){ 34 if(num+1>r){ 35 flag=false; 36 continue; 37 } 38 l=max(l,num+1); 39 } 40 else { 41 if(num>r){ 42 flag=false; 43 continue; 44 } 45 l=max(num,l); 46 } 47 } 48 } 49 else { 50 if(str[0]=='>'){ 51 if(str[1]=='='){ 52 if(num>r){ 53 flag=false; 54 continue; 55 } 56 l=max(l,num); 57 } 58 else { 59 if(num+1>r){ 60 flag=false; 61 continue; 62 } 63 l=max(num+1,l); 64 } 65 } 66 if(str[0]=='<'){ 67 if(str[1]=='='){ 68 if(num<l) { 69 flag=false; 70 continue; 71 } 72 r=min(r,num); 73 } 74 else { 75 if(num-1<l){ 76 flag=false; 77 continue; 78 } 79 r=min(r,num-1); 80 } 81 } 82 } 83 } 84 if(!flag){ 85 printf("Impossible "); 86 return ; 87 } 88 for(int i=l;i<=r;i++){ 89 printf("%d ",i); 90 return ; 91 } 92 93 } 94 int main(){ 95 int T; 96 while(scanf("%d",&T)!=EOF){ 97 solve(T); 98 } 99 }
E题填坑来了
题意:有一个n*n的方格,里面有m个棋子,每个棋子有自身的属性值p,现在有这样一个集合,集合内的棋子要满足都在一条斜线上,并且距离(斜线上的距离)要满足一个条件,dis(i,j)>=pi^2+pj^2+C(C为常数)
思路:假设xi>xj,那么dis(i,j)=xi-xj+1 xi-xj+1>=pi^2+pj^2+C ---> xi-pi^2>=xj+pj^2+C-1 假设左边为A[i],右边为B[i],这样每个点都有属性ai,bi,把每条斜线按照x的升序排列,然后用类似nlogn求LIS的方法求出每条斜线上最多,我设a=x-p^p b=x+p^p+c-1,那么肯定B[i]>A[i],也就是如果你在序列中找到了这个点插入的位置,就可以直接插入,因为B[i]不可能在前面
能在集合里面加几个点假设xi>xj>xk 那么dis(i,k)=dis(i,j)+dis(j,k)-1>=pi^2+2*pj^2+pk^2+2*C-1>pi^2+pk^2+C 也就是只要相邻的满足条件,那么这个点肯定跟整个集合里面的满足条件
1 #include <stdio.h> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <set> 6 #include <vector> 7 using namespace std; 8 const int maxn=1e5+10; 9 int n,m,C; 10 struct node{ 11 long long x,y,p; 12 node(){}; 13 long long a,b; 14 node(int x_,int y_,int p_):x(x_),y(y_),p(p_){ 15 a=x-p*p,b=x+p*p+C-1; 16 } 17 }; 18 vector<node> G1[2*maxn]; 19 vector<node> G2[2*maxn]; 20 set<int> s1; 21 set<int> s2; 22 set<int> ::iterator it; 23 int siznum; 24 bool cmp(const node&tmp1,const node&tmp2){ 25 return tmp1.x<tmp2.x; 26 } 27 int ans=0; 28 long long q[maxn]; 29 void cal(vector<node> G[2*maxn],set<int> s){ 30 for(it=s.begin();it!=s.end();it++){ 31 int num=*it; 32 int cnt=0; 33 sort(G[num].begin(),G[num].end(),cmp); 34 for(int i=0;i<G[num].size();i++){ 35 int pos=upper_bound(q,q+cnt,G[num][i].a)-q; 36 if(pos==cnt){ 37 q[cnt++]=G[num][i].b; 38 } 39 else { 40 if(q[pos]>G[num][i].b){ 41 q[pos]=G[num][i].b; 42 } 43 } 44 } 45 ans=max(ans,cnt); 46 } 47 } 48 node point[maxn]; 49 long long num[maxn<<1]; 50 void solve(){ 51 ans=0; 52 scanf("%d %d %d",&n,&m,&C); 53 for(int i=0;i<(2*maxn);i++) G1[i].clear(),G2[i].clear(); 54 s1.clear(),s2.clear(); 55 long long x,y,p; 56 for(int i=1;i<=m;i++){ 57 scanf("%lld %lld %lld",&x,&y,&p); 58 point[i]=node(x,y,p); 59 s1.insert(x+y); 60 s2.insert(y-x+maxn); 61 G1[x+y].push_back(point[i]); 62 G2[y-x+maxn].push_back(point[i]); 63 } 64 cal(G1,s1); 65 cal(G2,s2); 66 printf("%d ",ans); 67 } 68 int main(){ 69 int T; 70 freopen("bishops.in","r",stdin); 71 scanf("%d",&T); 72 while(T--){ 73 solve(); 74 } 75 }
C题放弃QAQ
非常感激大佬们挂题讲题QAQ