【B】:
【题目】: 回文串是指一个字符串,从左至右和从右至左看是相同的。例如
和
都是回文串。
现在有
个二进制字符串
(每个字符串都由
或
和
组成),现在可以交换一组字符任意次,两个字符可以来自同一个或者不同的字符串,没有严格要求。
也就是说
字符串中任一字符和
字符串中任一字符都可以交换,其中
和
可以是同一字符串也可是不同字符串。这种交换可进行任意次。
那么
个原始字符串通过任意次这样的交换可以最多得到几个回文字符串呢。
【思路】:
我们把输入的字符串分为三类:
字符串长度为单数。无论其内部有多少个
或
,它都可以通过交换的方法实现回文。在代码中个数计为
字符串长度为偶数且有偶数个
和偶数个
,一样,可以通过交换自己实现回文,个数计为
字符串长度为偶数且有奇数个
。此类不能通过交换自己变成回文,只能通过两两一组,然后组内两个字符串交换一个
和
,实现回文。当然,也可以和一个长度为奇数的字符串交换(注意这里的交换是指以
换
或以
换
),然后变为第二类字符串。这种字符串个数计为
【代码】:
#include <bits/stdc++.h>
using namespace std;
int n,ans,cnt,tot,i,ret;
inline int calc(string s){
register int ret=0;
for(int i=0;i<s.size();i++)
if (s[i]=='1') ret++;
return ret;
}
int test_number;
int main(){
cin>>test_number;
while (test_number--){
cin>>n;ans=cnt=tot=0;
for(i=1;i<=n;i++){
string s;cin>>s;
int v=calc(s);
if (s.size()&1) cnt++;
else if (v%2==0) ans++;
else tot++;
}
if (tot%2==0)
ret=ans+cnt+tot;
else{
if (ret) ret=ans+cnt+tot;
else ret=ans+cnt+tot-1;
}
printf("%d\n",ret);
}
return 0;
}
【D】:
【题目】: 给你一个
行
列的二维迷宫,一开始你在迷宫的左上角的格子
处(我们用位置
来表示第
行第
列),你要走到右下角的格子
出,但是你是不能随便走的,
行走的方向是有规定的:每一步你只能往右移动一格,或者往下移动一格,并且你不能移动出迷宫的边界;
迷宫中.
为可走的格子,*
为滑滑梯,可以直接滑到当前方向的下一个.
,但是不能滑出边界。
请问在这种限制下,你有多少种不同的移动方案。
说明:只要从起点到终点的移动路线不同,那么我们就说它们是不同的移动方案。比如:假设
,并且迷宫形状如样例输入一样的时候,
从左上角
移动到右下角
共有
种移动方案:
【附注】: 题目地图如下:
.*.
.*.
【思路】:
很简单的一道题,递推即可:
点
向上一步可以到达
点
向左一步可以到
点
到
的方案数
则有
代码中有一些细节:若
走一步会离开地图,那么
或
会等于
,所以的话,
或
会等于
,所以的话,就把不合法的情况删除了!
【代码】:
#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
char a[110][110];
int f[110][110],n,m,i,j;
int U[110][110],L[110][110];
int main(){
cin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
cin>>a[i][j];
for(i=1;i<=m;i++)
if (a[1][i]=='.')
U[1][i]=1;
else U[1][i]=0;
for(i=1;i<=n;i++)
if (a[i][1]=='.')
L[i][1]=1;
else L[i][1]=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++){
if (a[i-1][j]=='.')
U[i][j]=i-1;
else U[i][j]=U[i-1][j];
if (a[i][j-1]=='.')
L[i][j]=j-1;
else L[i][j]=L[i][j-1];
}
f[1][1]=1;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if ((i!=1||j!=1)&&a[i][j]=='.')
f[i][j]=(f[U[i][j]][j]+f[i][L[i][j]])%mod;
printf("%d",f[n][m]);
return 0;
}
【E】:
【思路】: 直接广搜,判重的话,直接用一个数组
表示是否在还剩
的体力时到达过点
,然后直接跑就可以
【代码】:
#include <bits/stdc++.h>
using namespace std;
int a[15][15],n,m,i,j;
bool flag[15][15][10];
struct node{
int x,y,step,hp;
};
const int dx[]={1,0,-1,0};
const int dy[]={0,1,0,-1};
inline bool check(int x,int y,int s){
if (x<1||x>n)
return false;
if (y<1||y>m)
return false;
if (!flag[x][y][s])
return false;
if (s==0)
return false;
if (a[x][y]==0)
return false;
return true;
}
inline int bfs(int bx,int by){
queue<node> q;
q.push((node){bx,by,0,6});
memset(flag,true,sizeof(flag));
flag[bx][by][6]=false;
while (q.size()){
node z=q.front();q.pop();
// printf("(%d,%d,%d,%d)\n",z.x,z.y,z.step,z.hp);
if (a[z.x][z.y]==3)
return z.step;
for(int i=0;i<4;i++){
int x=z.x+dx[i],y=z.y+dy[i];
if (!check(x,y,z.hp-1))
continue;
if (a[x][y]==4){
if (check(x,y,6)){
q.push((node){x,y,z.step+1,6});
flag[x][y][6]=false;
}
}
else{
q.push((node){x,y,z.step+1,z.hp-1});
flag[x][y][z.hp-1]=false;
}
}
}
return -1;
}
int bx,by;
int main(){
scanf("%d%d",&m,&n);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++){
scanf("%d",&a[i][j]);
if (a[i][j]==2){
bx=i;by=j;
}
}
cout<<bfs(bx,by);
return 0;
}