解题思路
Posted fridayfang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解题思路相关的知识,希望对你有一定的参考价值。
简要记录题解思路
f:battle City
bfs+优先队列
每次入队前进行标记,每次出队都上当前最短的路径
bfs+优先队列似乎就是dijkstra算法 ??
code
char mp[maxm][maxn];
int vis[maxm][maxn];//记录是否处理过
struct node{
int x,y;
int step;
node(int x_,int y_,int s_):x(x_),y(y_),step(s_){}
};
bool operator < (node a,node b){
return a.step>b.step;
}
int mv[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
//优先队列
int m,n;
int bfs(node begin,int endx,int endy){
priority_queue<node> que;
vis[begin.x][begin.y]=1;
que.push(begin);
while(!que.empty()){
node tmp=que.top();
que.pop();
//printf("db %d %d step %d
",tmp.x,tmp.y,tmp.step);
if(tmp.x==endx&&tmp.y==endy) return tmp.step;
int tmpx,tmpy,tmps;
for(int i=0;i<4;i++){
tmpx=tmp.x+mv[i][0];
tmpy=tmp.y+mv[i][1];
if(tmpx<0||tmpx>=m||tmpy<0||tmpy>=n||vis[tmpx][tmpy]||mp[tmpx][tmpy]=='S'||mp[tmpx][tmpy]=='R') continue;//依旧可能出现相同坐标都在队列中
else if(mp[tmpx][tmpy]=='B') tmps=tmp.step+2;
else tmps=tmp.step+1;
node t=node(tmpx,tmpy,tmps);
vis[tmpx][tmpy]=1;
que.push(t);
//else if(mp[tmpx][tmpy]=='B'){node t=node(tmpx,tmpy,tmp.step+2);vis[tmpx][tmpy]=1;que.push(t);}
//else if(mp[tmpx][tmpy]=='E'||mp[tmpx][tmpy]=='T'){node t=node(tmpx,tmpy,tmp.step+1);vis[tmpx][tmpy]=1;que.push(t);}
}
}
return -1;//no find
}
node beg=node(0,0,0);
int endx,endy;
int main(){
while(scanf("%d %d",&m,&n)&&m!=0){
//CL(mp,0);
CL(vis,0);
/*
while(!que.empty()){
que.pop();
}
*/
for(int i=0;i<m;i++){
scanf("%s",mp[i]);
for(int j=0;j<n;j++){
if(mp[i][j]=='Y'){
beg.x=i,beg.y=j,beg.step=0;
}
if(mp[i][j]=='T'){
endx=i,endy=j;
}
}
}
int ans=bfs(beg,endx,endy);
printf("%d
",ans);
}
return 0;
}
g: 从N个数里找出和为N的倍数
数学题(鸽巢原理)+前缀和
处理前缀和的模N为0和相同的情况
code
void output(int i,int j){
printf("%d
",j-i);
for(int t=i+1;t<=j;t++){
printf("%d
",a[t]);
}
}
int main(){
scanf("%d",&n);
//CL(tag,-1);
bool flag=false;//是否已经找到该组数据答案
for(int i=1;i<=n;i++){
scanf("%d",a+i);
if(flag) continue;
sum[i]=a[i];
sum[i]+=sum[i-1];
int mod=sum[i]%n;
if(mod==0){
output(0,i);
flag=true;
continue;
}
//printf("db %d %d mod %d tag[mod] %d
",i,sum[i],mod,tag[mod]);
if(tag[mod]==0){
tag[mod]=i;
}
else{
output(tag[mod],i);
flag=true;
}
}
return 0;
}
h :判断负环
bellman-ford
bellman-ford算法处理单源最短路(可以有负边),基本操作:
N-1次的松弛,每次松弛时对边<u,v> dis[v]=min(dis[v],dis[u]+cost(u,v))
不优化的复杂度O(NE)
code
struct Edge{
int u,v,w,next;
//Edge(int u_,int v_,int w_):u(u_),v(v_),w(w_) {}
}es[maxm];//maybe be not need u
int head[maxn];//head[u]链表头,边编号
int dis[maxn];
//init -1
int cnt;
void add(int u,int v,int w){
es[cnt].u=u;es[cnt].v=v;es[cnt].w=w;
es[cnt].next=head[u];
head[u]=cnt;
cnt++;
}
void bellman(int s){
//原点s进行bellmanford算法
CL(dis,0x3f);
dis[s]=0;// dis0
//dis1...dis(n-1)
//dis(n)[j]=min(dis(n-1)[j],dis(n-1)[i]+cost[i][j])
for(int t=1;t<=n-1;t++){
//优化之一如果有一次都没更新则停止
//便利所有边
for(int j=0;j<cnt;j++){
int u=es[j].u;
int v=es[j].v;
int w=es[j].w;
if(dis[v]>dis[u]+w) dis[v]=dis[u]+w;//更新
}
}
}
bool check(){
//n-1次后还能更新则存在负环
for(int j=0;j<cnt;j++){
int u=es[j].u;
int v=es[j].v;
int w=es[j].w;
if(dis[v]>dis[u]+w) return false;
}
return true;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d %d %d",&n,&m,&W);
//初始化
cnt=0;
CL(head,-1);
int u,v,w;
for(int i=0;i<m;i++){
scanf("%d %d %d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
for(int j=0;j<W;j++){
scanf("%d %d %d",&u,&v,&w);
w=0-w;
add(u,v,w);
}
//printf("cnt %d
",cnt);
bool tag=false;
//for(int i=1;i<=n;i++){//如果每个点都操作,不知道为什么回WA 而不是TLE,总之是很怪的题目
bellman(1);
if(!check()){
//printf("YES
");
tag=true;
//break;
}
//}
if(tag) printf("YES
");
else printf("NO
");
}
return 0;
}
I:正方形(找出N个整点构成的正方形个数)
手写hash+简单几何关系
枚举两点,得到正方形的另外两点,hash检索(注意选模,搜索时时搜索自由区域才停)
注意枚举重复情况(4条边都被枚举遍)
code
const int maxn=100007;
struct point{
int x,y;
int count;//标志有效位置
}hash[100007];
int n;
int xx[1005],yy[1005];
void tohash(int x,int y){
int pos=(x*x+y*y+x-y)%maxn;
while(hash[pos].count!=0){
pos=(pos+1)%maxn;
}
hash[pos].count=1;
hash[pos].x=x;hash[pos].y=y;
}
int search(int x,int y){
int pos=(x*x+y*y+x-y)%maxn;
while(hash[pos].count!=0){
if(hash[pos].x==x&&hash[pos].y==y) return 1;
pos=(pos+1)%maxn;
}
//printf("db search pos:%d x %d y %d
",pos,x,y);
//if(hash[pos].x==x&&hash[pos].y==y) return 1;
return 0;
}
int main(){
while(scanf("%d",&n)&&n!=0){
CL(hash,0);
int x,y;
for(int i=0;i<n;i++){
scanf("%d %d",&x,&y);
xx[i]=x,yy[i]=y;
tohash(x,y);
}
int ans=0;
//for(int i=0;i<=4;i++){
//printf("db i:%d %d %d %d
",i,hash[i].x,hash[i].y,hash[i].count);
//}
//printf("db %d %d
",search(0,0),search(0,1));
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(i==j) continue;
int x1=xx[i],x2=xx[j],y1=yy[i],y2=yy[j];
int dx=x2-x1,dy=y1-y2;
//(x1+dy,y1+dx) (x2+dy,y2+dx)
//(x1-dy,y1-dx) (x2-dy,y2-dx)
//printf("i:%d j:%d searchpoint1 %d %d %d %d piint2 %d %d %d %d
",i,j,x1+dy,y1+dx,x2+dy,y2+dx,x1-dy,y1-dx,x2-dy,y2-dx);
ans+=(search(x1+dy,y1+dx)&search(x2+dy,y2+dx));
ans+=(search(x1-dy,y1-dx)&search(x2-dy,y2-dx));
//printf("db ans %d
",ans);
}
}
printf("%d
",ans>>2);
}
return 0;
}
j:container
给出三维整点左边,要将这些区域包裹起来的最小表面积
6n-2m ;n是点的个数,m是相接的面
但没找到原题,无法测试
code
struct cell{
int x,y,z;
}cels[maxn];
int n;
bool checkadj(cell c1,cell c2){
return (abs(c1.x-c1.x)+abs(c1.y-c2.y)+abs(c1.z-c2.z))<=1;//no same
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d %d %d",&cels[i].x,&cels[i].y,&cels[i].z);
}
int ans=6*n;
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(checkadj(cels[i],cels[j])) ans-=2;
}
}
printf("%d
",ans);
}
return 0;
}
以上是关于解题思路的主要内容,如果未能解决你的问题,请参考以下文章