第一次写博客你们见谅........(若是有好心大佬有给个人代码改进意见欢迎加qq或者直接评论留言.感激涕零)
首先安利一个acm入门的网址(第一次写......)
https://www.zhihu.com/question/51727516/answer/127265733?utm_medium=social&utm_source=qq
首先是A题...
A题题意大概是输入a和b, a表明棋盘边长,b表明要放的棋子的数目.而后输入棋盘(棋盘中有空白区域没法放置棋子.)
要求输出放置的方案数目.
枚举一次枚举行,而后枚举行中的可放置棋子的位置.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int side,num,ans;
char line[9][9];
int check[9];
void bfs(int i,int k)
{
if(k==num)
{
ans++;
return;
}
if(i>=side)
return;
for(int j=0;j<side;j++)
{
if(line[i][j]=='#'&&check[j]==0)
{
check[j]=1;
bfs(i+1,k+1);
check[j]=0;
}
}
bfs(i+1,k);
}
int main()
{
while(scanf("%d%d",&side,&num)&&side!=-1)
{
ans=0;
memset(check,0,sizeof(check));
for(int i=0;i<side;i++)
{
scanf("%s",line[i]);
}
bfs(0,0);
printf("%d\n",ans);
}
return 0;
}
而后是B题...
B题是三维的dfs
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int a,b,c,ans;
char migong[41][41][41];
int vis[41][41][41];
int go[6][3]={{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}};
struct Node
{
int i;
int j;
int k;
int steps;
};
Node p;
Node q;
queue <Node> duiwu;
bool canGo(int i , int j , int k)
{
if(i<a&&j<b&&k<c&&i>=0&&j>=0&&k>=0)
return true;
return false;
}
void bfs()
{
while(!duiwu.empty())
{
q=duiwu.front();
duiwu.pop();
if(migong[q.i][q.j][q.k]=='E')
{
ans=q.steps;
printf("Escaped in %d minute(s).\n",ans);
return;
}
for(int m=0;m<6;m++)
{
p.i=q.i+go[m][0];
p.j=q.j+go[m][1];
p.k=q.k+go[m][2];
p.steps=q.steps+1;
if(canGo(p.i,p.j,p.k)&&vis[p.i][p.j][p.k]==0)
{
duiwu.push(p);
vis[p.i][p.j][p.k]=1;
}
}
}
printf("Trapped!\n");
}
int main()
{
while(scanf("%d%d%d",&a,&b,&c)&&a!=0)
{
memset(vis,0,sizeof(vis));
ans=0;
for(int i=0;i<a;i++)
{
for(int j=0;j<b;j++)
{
scanf("%s",migong[i][j]);
for(int k=0;k<c;k++)
{
if(migong[i][j][k]=='S')
{
p.i=i;
p.j=j;
p.k=k;
vis[i][j][k]=1;
p.steps=0;
duiwu.push(p);
}
if(migong[i][j][k]=='#')
{
vis[i][j][k]=1;
}
}
}
}
bfs();
while(!duiwu.empty())
{
duiwu.pop();
}
}
return 0;
}
接着是c.
c 的意思是从一个数变成另外一个.能够+1或者-1或者乘2
显然也是dfs.(建议多练练 虽然看起来很简单可是写起来得本身概括一套模板 ,以后写会很省时间
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int a,b,ans;
int vis[200000];//题目的范围是输入数据的范围,可是没有规定不能走出这个范围,因而可能走2倍的距离.
struct Node
{
int i;
int steps;
};
Node p;
Node q;
queue <Node> duiwu;
bool canGo(int i)
{
if(i<0||i>200000)
return false;
return true;
}
void bfs()
{
while(!duiwu.empty())
{
p=duiwu.front();
duiwu.pop();
if(p.i==b)
{
ans=p.steps;
printf("%d\n",ans);
return;
}
q.i=p.i-1;
q.steps=p.steps+1;
if(canGo(q.i)&&vis[q.i]==0)
{
duiwu.push(q);
vis[q.i]=1;
}
q.i=p.i+1;
q.steps=p.steps+1;
if(canGo(q.i)&&vis[q.i]==0)
{
vis[q.i]=1;
duiwu.push(q);
}
q.i=2*p.i;
q.steps=p.steps+1;
if(canGo(q.i)&&vis[q.i]==0)
{
duiwu.push(q);
vis[q.i]=1;
}
}
}
int main()
{
while(~scanf("%d%d",&a,&b))
{
memset(vis,0,sizeof(vis));
q.i=a;
q.steps=0;
vis[a]=1;
duiwu.push(q);
bfs();
while(!duiwu.empty())
duiwu.pop();
}
return 0;
}
接着是我wa了几十次的D题.
此题给个人感受是想必定比写重要.首先要保证想的是对的 否则对着一段从开始思路就错的代码和各类可能出现的错误乱找只是浪费时间.
题意就是输出m*n的灯的矩阵.而后要求输出最小反转次数的关闭全部灯 的方法.改变一个灯的状态会致使周围四灯状态的改变.
第一次我没有仔细读题并且本身贼菜.就感受和之前的关灯问题同样.直接从第二行开始最后判断最后一行的灯的状态.其实若是第一行的灯进行操做有可能使后面的关灯次数变少.而后上代码.....这题和字典序不要紧!!!!!若是测了多组数据都对最好上poj的discuss看一下.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int deng[16][16],tempdeng[16][16],turn[16][16],tempturn[16][16],ans,tmpans,a,b;
void flipLight(int i,int j)
{
tempdeng[i][j]=1^tempdeng[i][j];
if(i>0)
tempdeng[i-1][j]=1^tempdeng[i-1][j];
if(i<a-1)
tempdeng[i+1][j]=1^tempdeng[i+1][j];
if(j>0)
tempdeng[i][j-1]=1^tempdeng[i][j-1];
if(j<b-1)
tempdeng[i][j+1]=1^tempdeng[i][j+1];
}
void bfs(int m)
{
for(int i=0;i<b;i++)
{
if(m>>i&1)
{
flipLight(0,i);
tempturn[0][i]=1;
ans++;
}
}
for(int i=1;i<a;i++)
{
for(int j=0;j<b;j++)
{
if(tempdeng[i-1][j]==1)
{
flipLight(i,j);
tempturn[i][j]=1;
ans++;
}
}
}
for(int i=0;i<b;i++)
{
if(tempdeng[a-1][i]==1)
return;
}
if(tmpans>ans)
{
tmpans=ans;;
memcpy(turn,tempturn,sizeof(tempturn));
}
}
int main()
{
while(~scanf("%d%d",&a,&b))
{
tmpans=999999999;
for(int i=0;i<a;i++)
{
for(int j=0;j<b;j++)
{
scanf("%d",&deng[i][j]);
}
}
int temp=1<<b;
for(int i=0;i<temp;i++)
{
ans=0;
memset(tempturn,0,sizeof(tempturn));
memcpy(tempdeng,deng,sizeof(tempdeng));
bfs(i);
}
if(tmpans==999999999)
cout<<"IMPOSSIBLE"<<endl;
else
for(int i=0;i<a;i++)
{
for(int j=0;j<b;j++)
{
if(j!=b-1)
printf("%d ",turn[i][j]);
else
printf("%d",turn[i][j]);
}
cout<<endl;
}
}
return 0;
}
E题是.....emmm缓解心情的.寻找大于一个数的且只包含0.1的这个数的最小的公倍数 .它使用了哈夫曼思想.有没有特别好奇呢.其实要学习到思想是很难的 ,多半靠本身领悟和题目的洗礼.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int a;
long long int b[600005];
int main()
{
while(~scanf("%d",&a)&&a!=0)
{
b[0]=0;
b[1]=1;
int n=1;
while(b[n]%a!=0)
{
n++;
b[n]=10*b[n/2]+n%2;
}
printf("%I64d\n",b[n]);
}
return 0;
}
十分灵活..嗯.
F是很是明显的 dfs.
tle的可能:栈没有清空.进队伍没判重.还有多是判断不太对.既然bfs出去的结果大多不合法就先判断不合法直接跳过,否则会判断许屡次.引发tle.......上代码(勿喷....的确很不优雅.....
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct Node
{
int a,steps;
};
Node q,p;
int temp[5]={1,10,100,1000,10000};
queue <Node> duiwu;
int a,b,vis[10000];
bool ifPrime(int m)
{
for(int i=2;i<=m/2;i++)
{
if(m%i==0)
return false;
}
return true;
}
int bfs()
{
while(!duiwu.empty())
{
p=duiwu.front();
duiwu.pop();
if(p.a==b)
{
return p.steps;
}
for(int j=0;j<4;j++)
{
if(j<3)
{
for(int i=0;i<10;i++)
{
q.a=p.a%temp[j]+(p.a/temp[j+1])*temp[j+1]+i*temp[j];
if(vis[q.a]==1)
continue;
if(ifPrime(q.a))
{
q.steps=p.steps+1;
duiwu.push(q);
vis[q.a]=1;
}
}
}
else
for(int i=1;i<10;i++)
{
q.a=p.a%temp[j]+(p.a/temp[j+1])*temp[j+1]+i*temp[j];
if(vis[q.a]==1)
continue;
if(ifPrime(q.a)&&vis[q.a]==0)
{
q.steps=p.steps+1;
duiwu.push(q);
vis[q.a]=1;
}
}
}
}
return -1;
}
int main()
{
int k;
scanf("%d",&k);
while(k--)
{
while(!duiwu.empty())
{
duiwu.pop();
}
scanf("%d%d",&a,&b);
memset(vis,0,sizeof(vis));
q.a=a;
vis[a]=1;
q.steps=0;
duiwu.push(q);
printf("%d\n",bfs());
}
return 0;
}