3.11考试

1、贪吃蛇(CJOJ P2185)


第一眼是深搜,于是考场上写了个啥都不加的。。50分

#include<cstdio>
#include<algorithm>
using namespace std;
bool Z[22][22];
struct data{int x,y;}que[1001];
int hd=1,tl,ans=1000000000;
inline int gi(){
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x;
}
int n,m;
const int X[]={23333,-1,0,1,0},Y[]={333333,0,-1,0,1};
inline void dfs(int x,int y,int b){
	if(b>ans)return;
	if(x==1&&y==1){ans=b;return;}
	int tx=que[hd].x,ty=que[hd].y;
	for(int i=1;i<=4;i++){
		register int nx=que[tl-1].x+X[i],ny=que[tl-1].y+Y[i];
	    if(!Z[nx][ny]){
	    	Z[tx][ty]=0,Z[nx][ny]=1;
	    	que[tl]=(data){nx,ny};
			++hd,++tl;
	    	dfs(nx,ny,b+1);
	    	Z[tx][ty]=1,Z[nx][ny]=0;
	    	--hd,--tl;
		}
	}
}
int main(){
    n=gi(),m=gi();
    for(int i=1;i<=m;i++)Z[0][i]=Z[n+1][i]=1;
    for(int i=1;i<=n;i++)Z[i][0]=Z[i][m+1]=1;
    int a,b,l=gi(),k;
    tl=l+1;
    for(int i=l;i;i--){
    	que[i].x=gi(),que[i].y=gi();
    	Z[que[i].x][que[i].y]=1;
    }
	k=gi();
    while(k--)a=gi(),b=gi(),Z[a][b]=1;
    dfs(que[l].x,que[l].y,0);
    printf("%d\n",ans);
	return 0;
}
 

经ZJO大神指点,写了个迭代,再加剪枝。。90分。。第9个点S也过不去

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
bool Z[22][22];
struct data{int x,y;}que[1001];
int hd=1,tl;
inline int gi(){
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x;
}
int n,m,flag=0;
const int X[]={23333,-1,0,1,0},Y[]={333333,0,-1,0,1};
inline void dfs(int x,int y,int b,int maxx){
	if(b==maxx){
	    if(x==1&&y==1){
	    	printf("%d\n",maxx);
	    	exit(0);
	    }
	    return;
	}
	if(b+x+y-2>maxx)return;//剪枝
	int tx=que[hd].x,ty=que[hd].y;
	for(int i=1;i<=4;i++){
		register int nx=que[tl-1].x+X[i],ny=que[tl-1].y+Y[i];
	    if(!Z[nx][ny]){
	    	Z[tx][ty]=0,Z[nx][ny]=1;
	    	que[tl]=(data){nx,ny};
			++hd,++tl;
	    	dfs(nx,ny,b+1,maxx);
	    	Z[tx][ty]=1,Z[nx][ny]=0;
	    	--hd,--tl;
		}
	}
}
int main(){
    n=gi(),m=gi();
    for(int i=1;i<=m;i++)Z[0][i]=Z[n+1][i]=1;
    for(int i=1;i<=n;i++)Z[i][0]=Z[i][m+1]=1;
    int a,b,l=gi(),k;
    tl=l+1;
    for(int i=l;i;i--){
    	que[i].x=gi(),que[i].y=gi();
    	Z[que[i].x][que[i].y]=1;
    }
	k=gi();
    while(k--)a=gi(),b=gi(),Z[a][b]=1;
    int i;
    for(i=1;;i++)dfs(que[l].x,que[l].y,0,i);
	return 0;
}
再加个SPFA与处理出最短距离,再用它来剪枝,过了。。。但个人分析有时也会被卡的没答案,然而数据水还是A了(以下为丑的一比的代码)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
int Z[22][22];
struct data{int x,y;}que[1001];
int hd=1,tl,hehe [22][22];
inline int gi(){
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x;
}
int n,m,flag=0;
const int X[]={23333,-1,0,1,0},Y[]={333333,0,-1,0,1};
void spfa(){
	int que[500],in[22][22]={0};
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		    hehe[i][j]=10000000;
	hehe[1][1]=0;
	in[1][1]=1;
	que[1]=0;
	int hd=1,tl=2;
	while(hd^tl){
		int fx=que[hd]/m+1,fy=que[hd]%m+1;
		for(int i=1;i<=4;i++){
			int nx=fx+X[i],ny=fy+Y[i];
			if(Z[nx][ny]!=2&&hehe[nx][ny]>hehe[fx][fy]+1){
			    hehe[nx][ny]=hehe[fx][fy]+1;
			    if(!in[nx][ny]){
			    	in[nx][ny]=1;
				    que[tl++]=(nx-1)*m+ny-1;
				    if(tl==450)tl=1;
				}
			}
		}
		hd++;
		if(hd==450)hd=1;
		in[fx][fy]=0;
	}
}
inline void dfs(int x,int y,int b,int maxx){
	if(b==maxx){
	    if(x==1&&y==1){
	    	printf("%d\n",maxx);
	    	exit(0);
	    }
	    return;
	}
	if(b+hehe[x][y]>maxx)return;
	int tx=que[hd].x,ty=que[hd].y;
	for(int i=1;i<=4;i++){
		register int nx=que[tl-1].x+X[i],ny=que[tl-1].y+Y[i];
	    if(!Z[nx][ny]){
	    	Z[tx][ty]=0,Z[nx][ny]=1;
	    	que[tl]=(data){nx,ny};
			++hd,++tl;
	    	dfs(nx,ny,b+1,maxx);
	    	Z[tx][ty]=1,Z[nx][ny]=0;
	    	--hd,--tl;
		}
	}
}
int main(){
    n=gi(),m=gi();
    for(int i=1;i<=m;i++)Z[0][i]=Z[n+1][i]=1;
    for(int i=1;i<=n;i++)Z[i][0]=Z[i][m+1]=1;
    int a,b,l=gi(),k;
    tl=l+1;
    for(int i=l;i;i--){
    	que[i].x=gi(),que[i].y=gi();
    	Z[que[i].x][que[i].y]=1;
    }
	k=gi();
    while(k--)a=gi(),b=gi(),Z[a][b]=2;
    spfa();
	int i;
    for(i=1;;i++)dfs(que[l].x,que[l].y,0,i);
	return 0;
}

2、晨跑路径(CJOJ P1956)


第一眼水题,写了Tarjan

第二眼暴力,果断删了Tarjan,枚举删每一条边(还Tarjan,What a Sabi I am!)

然而还是WA了,链式前向星没乘2。。。(What a Sabi I am!还有为什么这段代码震惊了整个机房)

AC:

#include<cstdio>
#include<algorithm>
#include<cstring>
#define t (dis[i])
using namespace std;
const int maxn=2010,maxm=8010<<1;
int fir[maxn],nxt[maxm],dis[maxm];
int n,m;
inline void adde(int fr,int to,int id){nxt[id]=fir[fr],fir[fr]=id,dis[id]=to;}
inline int gi(){
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x;
}
bool vis[maxn];
int ans[maxn],Ans=0;
inline void dfs(int now){
	vis[now]=1;
	for(int i=fir[now];i;i=nxt[i])
	    if(!vis[t])dfs(t);
}
int main(){
	n=gi(),m=gi();
	int a,b;
	for(int i=1;i<=m;i++)
		a=gi(),b=gi(),adde(a,b,i<<1),adde(b,a,i<<1|1);
	for(int i=2;i<n;i++){
		memset(vis,0,sizeof vis);
		vis[i]=1;
		dfs(1);
		if(vis[n]==0)ans[++Ans]=i;
	}
	printf("%d\n",Ans);
	for(int i=1;i<=Ans;i++)printf("%d ",ans[i]);
	return 0;
}
3、任务安排(CJOJ P1371)


额啊啊啊DP啊各种单调队列斜率优化什么的都来啦

感谢QT666大神指点,有了这段代码

#include<cstdio>
#include<algorithm>
#define C(j,i) (F[j]+s*(W[n]-W[j])+T[i]*(W[i]-W[j]))
using namespace std;
inline int gi(){
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x;
}
int T[5011],W[5011];
long long F[5011];
int n,s;
int main(){
#ifndef xzz
#endif
	n=gi(),s=gi();
	for(int i=1;i<=n;i++)
		T[i]=T[i-1]+gi(),W[i]=W[i-1]+gi();
	for(int i=1;i<=n;i++){
		F[i]=C(0,i);
	    for(int j=1;j<i;j++)
	    	F[i]=min(F[i],C(j,i));
	}
	printf("%lld",F[n]);
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值