不会写题解,只爱写总结(hhh)
感觉这套题整体还可以,没啥难题,但是又都有点意思,蒟蒻的我很多题都不是一发才过,还是太急了点,没怎么检查,立马就交了
比赛延长了一个小时,还是没做出来。。。
看题目就知道是三向bfs,但是奈何我的bfs太过于暴力,赛后看晖晖大佬的代码才A过
需要注意的是:
1、小h能走八个方向;小z和小y只能走四个方向
2、小h一秒最多能走3步;小z和小y一秒最多只能走1步
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxm=5000010;
const int maxn=1e5+5;
char mp[1010][1010];
bool vis[3][1010][1010];
int n,m;
int dir[8][2]={0,1,0,-1,-1,0,1,0,-1,1,-1,-1,1,1,1,-1};
struct node{
int x,y;
node(int xx,int yy){
x=xx,y=yy;
}
};
queue<node>q[3];
int check(int x,int y,int id){
if(x>=1&&x<=n&&y>=1&&y<=m&&vis[id][x][y]==0&&mp[x][y]!='#')
return 1;
return 0;
}
int bfs(int x){
int num=q[x].size();
while(num--){
node now=q[x].front();
q[x].pop();
for(int i=0;i<8;i++){
if(i>=4&&(x==0||x==1)){
break;
}
int fx=now.x+dir[i][0];
int fy=now.y+dir[i][1];
if(check(fx,fy,x)){
vis[x][fx][fy]=1;
q[x].push(node(fx,fy));
if(vis[0][fx][fy]&&vis[1][fx][fy]&&vis[2][fx][fy]){
return 1;
}
}
}
}
return 0;
}
int solve(){
int dis=0;
while(!q[0].empty()||!q[1].empty()||!q[2].empty()){
++dis;
if(bfs(0)){
return dis;
}
if(bfs(1)){
return dis;
}
for(int i=1;i<=3;i++){
if(bfs(2)){
return dis;
}
}
}
return -1;
}
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++){
scanf("%s",mp[i]+1);
}
while(!q[0].empty()){
q[0].pop();
}
while(!q[1].empty()){
q[1].pop();
}
while(!q[2].empty()){
q[2].pop();
}
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]=='z'){
vis[0][i][j]=1;
q[0].push(node(i,j));
}
else if(mp[i][j]=='y'){
vis[1][i][j]=1;
q[1].push(node(i,j));
}
else if(mp[i][j]=='h'){
vis[2][i][j]=1;
q[2].push(node(i,j));
}
}
}
//printf("%d %d\n",p1.x,p1.y);
//printf("%d %d\n",p2.x,p2.y);
//printf("%d %d\n",p3.x,p3.y);
int ans=solve();
if(ans==-1){
printf("lack of junxun\n");
}
else{
printf("%d\n",ans);
}
}
return 0;
}
不光是津津不高兴了,我也不高兴了。这题输入居然是字符串,我也是醉了,搞的wa了三发
重点注意下这个即可,然后可能还有一个地方就是如果不高兴程度相同,则选择前面的
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxn=1e5+5;
int a[10],b[10];
string s;
int main() {
for(int i=1; i<=7; i++) {
cin>>s;
a[i]=s[0]-'0';
b[i]=s[1]-'0';
}
int maxnum=0;
int ans=0;
for(int i=1; i<=7; i++) {
if((a[i]+b[i])>8) {
if((a[i]+b[i])>maxnum) {
ans=i;
maxnum=(a[i]+b[i]);
}
}
}
printf("%d\n",ans);
return 0;
}
虽然题目有点长,但是不难发现其实就是贪心的思想,我们用一结构体存花生的坐标和值;然后对值从大到小排序;然后再找。
需要注意的是:当选择对排序后的下一堆花生采摘时,需要考虑:采摘完之后能否回到道路
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxn=1e5+5;
int mp[30][30];
struct node{
int x,y;
int num;
};
node a[410];
int n,m,k;
bool cmp(node xx,node yy){
return xx.num>yy.num;
}
int main(){
int t=0;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&mp[i][j]);
if(mp[i][j]!=0){
a[t].x=i,a[t].y=j;
a[t].num=mp[i][j];
t++;
}
}
}
sort(a,a+t,cmp);
int prex=0,prey=a[0].y;
int ans=0,cnt=0;
for(int i=0;i<t;i++){
int dis=abs(a[i].x-prex)+abs(a[i].y-prey);
if((dis+cnt+a[i].x+1)<=k){
cnt+=dis+1;
ans+=a[i].num;
prex=a[i].x,prey=a[i].y;
}
else{
break;
}
}
printf("%d\n",ans);
很明显的建树,遍历树,但是如果按照传统的建树之后再遍历似乎显得有点麻烦,而且没有必要;本来建树和遍历的过程就是递归的过程,那我们为何不用递归的思想直接求呢
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxn=1e5+5;
char s[maxn];
void solve(int l,int r){
int mid=(l+r)/2;
if(l!=r){
solve(l,mid);
solve(mid+1,r);
}
int flag1=0,flag2=0;
for(int i=l;i<=r;i++){
if(s[i]=='0')
flag1=1;
else
flag2=1;
}
if(flag1&&flag2){
printf("F");
}
else if(flag1){
printf("B");
}
else{
printf("I");
}
}
int main(){
int n;
scanf("%d",&n);
scanf("%s",s+1);
solve(1,strlen(s+1));
printf("\n");
return 0;
}
全排列问题,但是需要注意的是:当得到结果后,需要结束全排列,不然肯定会超时。
有两种方法:
1、C++全排列函数,有时候比赛中,为了节省时间,这何尝不是一种好方法
2、递归,也很简单
C++全排列函数版本
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxn=1e5+5;
int a[10010];
int n,m;
int main(){
scanf("%d",&n);
scanf("%d",&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int cnt=0;
do{
cnt++;
if(cnt==m+1){
printf("%d",a[1]);
for(int i=2;i<=n;i++){
printf(" %d",a[i]);
}
printf("\n");
break;
}
}while(next_permutation(a+1,a+n+1));
return 0;
}
这题可能题意会有点小难理解,它是求将多种方案能经过的城市去重求和
可能还是比较容易想到用BFS,但是发现城市数很大,不能用链接矩阵存,那我们就用邻接链表吧,链表可能比较麻烦,于是我们就用数组模拟链表:链式向前星存图
链式向前星(数组模拟邻接表)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxm=5000010;
const int maxn=1e5+5;
struct Edge{
int val,nxt;
}edge[maxn*2];
struct node{
int num,dis;
node(int x,int d){
num=x,dis=d;
}
};
int head[maxn],tot;
int ans=0,vis[maxn];
int n,m,p;
void add(int u,int v){
edge[tot].val=v;
edge[tot].nxt=head[u];
head[u]=tot++;
}
void init(){
memset(head,-1,sizeof(head));
tot=0;
}
void bfs(){
queue<node>q;
q.push(node(1,0));
vis[1]=1;
ans++;
while(!q.empty()){
node now=q.front();
q.pop();
if(now.dis==p){
break;
}
for(int i=head[now.num];i!=-1;i=edge[i].nxt){
int v=edge[i].val;
if(vis[v]==0){
vis[v]=1;
q.push(node(v,now.dis+1));
ans++;
}
}
}
return ;
}
int main(){
init();
scanf("%d%d%d",&n,&m,&p);
int u,v;
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
ans=0;
bfs();
printf("%d\n",ans);
return 0;
}
还是很容易想到栈应用的,我们可以开三个栈,分别存{、[、(、
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxn=1e5+5;
string s;
int main(){
cin>>s;
stack<int>st1,st2,st3;
int len=s.length();
for(int i=0;i<len;i++){
if(s[i]=='{'){
st1.push(i);
}
else if(s[i]=='['){
st2.push(i);
}
else if(s[i]=='(')
st3.push(i);
else if(s[i]=='}'){
printf("%d %d\n",st1.top(),i);
st1.pop();
}
else if(s[i]==']'){
printf("%d %d\n",st2.top(),i);
st2.pop();
}
else if(s[i]==')'){
printf("%d %d\n",st3.top(),i);
st3.pop();
}
}
return 0;
}
约瑟夫环,数据比较弱,我们用模拟完全可以过,但是也可以找下小规律
模拟法:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxn=1e5+5;
int t,n,m;
vector<int>ve;
int flag[maxn];
int main(){
vector<int>::iterator it;
scanf("%d",&t);
while(t--){
ve.clear();
memset(flag,0,sizeof(flag));
scanf("%d%d",&n,&m);
int cnt=0;
int ans=0;
while(flag[1]==0){
for(int i=1;i<=n;i++){
if(flag[i]==0){
cnt++;
}
if(flag[i]==0&&cnt==m){
cnt=0;
flag[i]=1;
//cout<
ans++;
}
if(flag[1]){
break;
}
}
if(flag[1])
break;
}
//cout<
printf("%d\n",ans-1);
}
return 0;
}
找规律,直接得答案(一个学弟想出来的):
#include
using namespace std;
int main()
{
int t,n,m;
cin>>t;
while(t--)
{
cin>>n>>m;
int num=1,ans=0,len=n;
while(num!=m)
{
int w=num;
ans+=(len+num-1)/m;
num=(len+num-1)%m+1;
len-=(len+w-1)/m;
}
cout<<ans<<endl;
}
}
和F题很像,也是数比较大,我们只能用链式向前星存图,然后这里是求每个城市与其相邻的城市,按照输入顺序输出;我们只要在创建图的时候,同时开个数组存下每个城市相邻的城市即可,具体见代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxm=5000010;
const int maxn=1e5+5;
struct Edge{
int val,nxt;
}edge[maxn*2];
int head[maxn],tot;
int n,m;
int vis[maxn];
struct node{
int num,dis;
node(int x,int d){
num=x,dis=d;
}
};
vector<int>ve[maxn];
void add(int u,int v){
edge[tot].val=v;
edge[tot].nxt=head[u];
head[u]=tot++;
ve[u].push_back(v);
}
void init(){
memset(head,-1,sizeof(head));
tot=0;
}
void solve(){
for(int i=1;i<=n;i++){
printf("%d",ve[i][0]);
for(int j=1;j<ve[i].size();j++){
printf(" %d",ve[i][j]);
}
printf("\n");
}
return ;
}
int main(){
init();
scanf("%d%d",&n,&m);
int u,v;
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
solve();
return 0;
}
这题就有点离谱,我用了个set,然后这题就特别水了
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const double eps=1e-8;
const int maxn=1e3+10;
const ll mod=1e9+7;
int n,m,p;
set<int>st;
int main() {
while(~scanf("%d%d%d",&n,&m,&p)) {
st.clear();
int u,v;
for(int i=1; i<=m; i++) {
scanf("%d%d",&u,&v);
if(u==p){
st.insert(v);
}
else if(v==p){
st.insert(u);
}
}
printf("%d\n",st.size());
}
return 0;
}