2021.10.03模拟赛


1.cheese

算法思路:dfs
我的代码:

#include<bits/stdc++.h>
using namespace std;
long long t,n,h,r;
struct point{
	long long x,y,z;
}p[1005];
bool vis[1005],flag;
double dist(point a,point b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
void dfs(int cnt){
	vis[cnt]=true;
	if(p[cnt].z>=h-r){
		flag=true;
		return ;
	}
	for(int i=1;i<=n&&!flag;i++)
		if(dist(p[cnt],p[i])<=r*2&&!vis[i])
			dfs(i);
}
int main(){
	scanf("%d",&t);
	for(int i=1;i<=t;i++){
		flag=false;
		memset(vis,0,sizeof(vis));
		scanf("%d%d%d",&n,&h,&r);
		for(int i=1;i<=n;i++)
			scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
		for(int i=1;i<=n;i++)
			if(p[i].z<=r&&!vis[i])
				dfs(i);
		if(flag)puts("Yes");
		else puts("No");
	}
}

估分:100
实际得分:100
反思:要开long long。

2.complexity

算法思路:要用树?
可能的思路:利用栈模拟。
标程:

#include<bits/stdc++.h>
#define ll long long
#define rint register int
using namespace std;
stack<int> zhan;
int main(){
    int t;scanf("%d",&t);
    while(t--){
        int n;scanf("%d",&n);
    	int nowline=0,pos=0;
    	int Fcnt=0,Ecnt=0,cnt=0;
        int hisans=0,myans=0;
        int runflag=-1;
    	bool endflag=false;
        string tmp;cin>>tmp;
        string sublist="0";
        for(rint i=0;i<tmp.length();++i)
            if(tmp[i]>='0'&&tmp[i]<='9'){
                hisans+=tmp[i]-'0';
                hisans*=10;
            }
        hisans/=10;
        if(tmp[2]=='1') hisans=0;
        for(rint i=1;i<=n;++i){
            string sub,opt,tmpsta,tmpend;
            int sta=0,end=0;
            cin>>opt;
            if(opt=="F"){
            	++Fcnt;++pos;
                zhan.push(pos);
                cin>>sub>>tmpsta>>tmpend;
                if(tmpend[0]=='n'&& (!(tmpsta[0]=='n'&&tmpend[0]=='n'))) ++cnt;
                for(rint j=0;j<tmpsta.length();++j){
                    sta+=tmpsta[j]-'0';
                    sta*=10;
                }
                sta/=10;
                if(tmpend[0]!='n'){//如果end是数字 
                    for(rint i=0;i<tmpend.length();++i){
                        end+=tmpend[i]-'0';
                        end*=10;
                    }
                    end/=10;
                    if(sta>end)//如果循环不能执行 
                        runflag=pos;
                }
                if(runflag==-1||pos<runflag) myans=max(myans,cnt);
                sublist+=sub;
                if(sublist.find(sub)!=sublist.length()-1){
                	printf("ERR\n");cnt=0;nowline=i;endflag=true;break;
                }
                sta=0;end=0;
            }
            else if(opt=="E"){
            	--cnt;++Ecnt;
                if(zhan.empty()&&!endflag){
            		printf("ERR\n");cnt=0;nowline=i;endflag=true;break;
                }
                if(zhan.top()<=runflag){
                	pos=0;
                	runflag=-1;
                }
                if(!zhan.empty()) zhan.pop();
                if(sublist.length()>0) sublist=sublist.substr(0,sublist.length()-1);
            	if(zhan.empty()) cnt=0;
            }
        }
        if(endflag){
        	cnt=0;
        	while(!zhan.empty())
        		zhan.pop();
        		string cnm;
        	for(rint i=1;i<=n-nowline+1;++i) getline(cin,cnm);
        	continue;
        }
        if(Fcnt!=Ecnt){
        	if(!endflag) printf("ERR\n");
        	while(!zhan.empty()) zhan.pop();
        	cnt=0;
        	continue;
        }
        while(!zhan.empty()) zhan.pop(); 
        if(!endflag){
        	if(myans==hisans) printf("Yes\n");
        	else printf("No\n");
        }
        myans=hisans=0;
    }
    return 0;
}

我的代码:

#include<bits/stdc++.h>
using namespace std;
int t,l,jie,fn,lf,cnt,maxx;
string m,start,end;
char type,name;
bool use[200],flag;
int decode(string m){
	if(m[2]=='1')return 0;
	else return (m[4]-48);
}
struct point{
	int kind,fa;
	vector<int> child;
}n[105]; 
void add(int a,int b){
	n[a].child.push_back(b);
	n[b].fa=a;
}
void dfs(int x,int j){
	maxx=max(maxx,j);
	if(n[x].kind==-1)
		return ;
	if(n[x].kind==1)
		j++;
	for(int i=0;i<n[x].child.size();i++)
		dfs(n[x].child[i],j);
	maxx=max(maxx,j);
	return ;
}
int read(string x){
	int len=x.size();
	int sum=0,base=1;
	for(int i=0;i<len;i++){
		sum*=base;
		sum+=x[i]-48;
		base*=10; 
	}
	return sum;
}
int main(){
	scanf("%d",&t);
	fn=0;
	n[0].kind=0;
	for(int i=1;i<=t;i++){
		flag=true;
		memset(use,false,sizeof(use));
		for(int i=1;i<=104;i++){
			n[i].kind=0;
			n[i].fa=0;
			n[i].child.clear();
		}
		lf=cnt=maxx=0;
		scanf("%d",&l);
		cin>>m;
		jie=decode(m);
		for(int i=1;i<=l;i++){
			cin>>type;
			if(type=='F'){
				lf++;
				cnt++;
				add(fn,cnt);
				fn=cnt;
				cin>>name>>start>>end;
				if(use[name])flag=false;
				use[name]=true;
				if(start=="n")n[cnt].kind=-1;
				else if(end=="n")n[cnt].kind=1;
				else{
					int st=read(start);
					int ed=read(end);
					if(st>ed)n[cnt].kind=-1;
					else n[cnt].kind=0;
				}
			}
			else{
				if(lf==0)flag=false;
				lf--;
				fn=n[fn].fa;
			}
		}
		if(!flag||lf>0){
			puts("ERR");
			continue;
		}
		dfs(0,0);
		if(maxx==jie)puts("Yes");
		else puts("No");
	}
}

估分:0
实际得分:27
反思:注意细节,不要盲目追求难答案。

3.classroom

算法思路:暂无
可能的思路:最短路+数学
标程:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e3 + 5;
const double inf = 1e17 + 5;
int n, m, v, e, c[MAXN][2], mp[305][305];
double k[MAXN], dp[MAXN][MAXN][2], ans;
inline int read() {
    char ch = getchar(); int u = 0, f = 1;
    while (!isdigit(ch)) {if (ch == '-')f = -1; ch = getchar();}
    while (isdigit(ch)) {u = u * 10 + ch - 48; ch = getchar();}return u * f;
}
int main(){
    memset(mp, 63, sizeof(mp));
    n = read(); m = read(); v = read(); e = read();
    for (register int i = 1; i <= n; i++)c[i][0] = read();
    for (register int i = 1; i <= n; i++)c[i][1] = read();
    for (register int i = 1; i <= n; i++)scanf("%lf", &k[i]);
    for (register int i = 1; i <= e; i++){
        int x = read(), y = read(), w = read();
        mp[x][y] = mp[y][x] = min(mp[x][y], w);
    }
    for (register int k = 1; k <= v; k++)
        for (register int i = 1; i <= v; i++)
            for (register int j = 1; j <= v; j++)
                mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
    for (register int i = 1; i <= v; i++)mp[i][i] = mp[i][0] = mp[0][i] = 0;
    for (register int i = 0; i <= n; i++)
        for (register int j = 0; j <= m; j++)dp[i][j][0] = dp[i][j][1] = inf;
    dp[1][0][0] = dp[1][1][1] = 0;
    for (register int i = 2; i <= n; i++){
        dp[i][0][0] = dp[i - 1][0][0] + mp[c[i - 1][0]][c[i][0]];
        for (register int j = 1; j <= min(i, m); j++){
            int C1 = c[i - 1][0], C2 = c[i - 1][1], C3 = c[i][0], C4 = c[i][1];
            dp[i][j][0] = min(dp[i][j][0], min(dp[i - 1][j][0] + mp[C1][C3], dp[i - 1][j][1] + mp[C1][C3] * (1 - k[i - 1]) + mp[C2][C3] * k[i - 1]));
            dp[i][j][1] = min(dp[i][j][1], min(dp[i - 1][j - 1][0] + mp[C1][C3] * (1 - k[i]) + mp[C1][C4] * k[i], dp[i - 1][j - 1][1] + mp[C2][C4] * k[i] * k[i - 1] + mp[C2][C3] * k[i - 1] * (1 - k[i]) + mp[C1][C4] * (1 - k[i - 1]) * k[i] + mp[C1][C3] * (1 - k[i - 1]) * (1 - k[i])));
        }
    }
    ans = inf;
    for (register int i = 0; i <= m; i++)ans = min(ans, min(dp[n][i][0], dp[n][i][1]));
    printf("%.2lf", ans);
    return 0;
}

估分:0
实际得分:0
反思:要观察每一道题,不要留空。

4.landlords

算法思路:暴力搜索
可能的思路:搜索+优化!!!
我的代码:

#include<bits/stdc++.h>
using namespace std;
int t,n,num,m,p[25][25],shen,minn=100000;
void copy(int step){
	for(int i=0;i<=14;i++)p[step+1][i]=p[step][i];
}
void dfs(int step){
	if(shen==0)return ;
		for(int i=0;i<=14;i++){ 
		if(p[step][i]>=4){ 
			for(int j=0;j<=14;j++){
				if(j==i)continue;
				if(p[step][j]>0){ 
					for(int k=0;k<=14;k++){
						if(k==i||k==j)continue;
						if(p[step][k]>0){ 
							copy(step);
							p[step+1][i]-=4;
							p[step+1][j]-=1;
							p[step+1][k]-=1;
							shen-=6;
							if(shen==0)minn=min(minn,step);
							dfs(step+1);
							shen+=6;
						} 
					} 
				}
			}
			for(int j=0;j<=14;j++){
				if(j==i)continue;
				if(p[step][j]>1){ 
					for(int k=0;k<=14;k++){
						if(k==i||k==j)continue;
						if(p[step][k]>1){ 
							copy(step);
							p[step+1][i]-=4;
							p[step+1][j]-=2;
							p[step+1][k]-=2;
							shen-=8;
							if(shen==0)minn=min(minn,step);
							dfs(step+1);
							shen+=8;
						} 
					} 
				}
			}
		} 
	}
	for(int i=0;i<=14;i++){
		if(p[step][i]>=3)  
			for(int j=0;j<=14;j++){
				if(j==i)continue;
				if(p[step][j]>1){ 
					copy(step);
					p[step+1][i]-=3;
					p[step+1][j]-=2;
					shen-=5;
					if(shen==0)minn=min(minn,step);
					dfs(step+1);
					shen+=5;
				}
			}
	}
	for(int i=3;i<=14;i++){
		for(int j=2;i+j-1<=14;j++){
			bool can=true;
			for(int k=i;k<=i+j-1&&can;k++)
				if(p[step][k]<3)can=false;
			if(!can)continue;
			copy(step);
			for(int k=i;k<=i+j-1;k++)
				p[step+1][k]-=3;
			shen-=3*j;
			if(shen==0)minn=min(minn,step);
			dfs(step+1);
			shen+=3*j;
		}
	}
	for(int i=3;i<=14;i++){
		for(int j=3;i+j-1<=14;j++){
			bool can=true;
			for(int k=i;k<=i+j-1&&can;k++)
				if(p[step][k]<2)can=false;
			if(!can)continue;
			copy(step);
			for(int k=i;k<=i+j-1;k++)
				p[step+1][k]-=2;
			shen-=2*j;
			if(shen==0)minn=min(minn,step);
			dfs(step+1);
			shen+=2*j;
		}
	}
	for(int i=0;i<=14;i++){
		if(p[step][i]>=3) 
			for(int j=0;j<=14;j++){
				if(j==i)continue;
				if(p[step][j]>0){ 
					copy(step);
					p[step+1][i]-=3;
					p[step+1][j]--;
					shen-=4;
					if(shen==0)minn=min(minn,step);
					dfs(step+1);
					shen+=4;
				} 
			}
	}
	for(int i=3;i<=14;i++){
		for(int j=5;i+j-1<=14;j++){
			bool can=true;
			for(int k=i;k<=i+j-1&&can;k++)
				if(p[step][k]<1)can=false;
			if(!can)continue;
			copy(step);
			for(int k=i;k<=i+j-1;k++)
				p[step+1][k]-=1;
			shen-=1*j;
			if(shen==0)minn=min(minn,step);
			dfs(step+1);
			shen+=1*j;
		}
	}
	for(int i=0;i<=14;i++){
		for(int j=1;j<=p[step][i];j++){
			copy(step);
			p[step+1][i]-=1;
			shen-=j;
			if(shen==0)minn=min(minn,step);
			dfs(step+1);
			shen+=j;
		}
	}
}
int main(){
	scanf("%d%d",&t,&n);
	for(int q=1;q<=t;q++){
		memset(p,0,sizeof(p)); 
		for(int i=1;i<=n;i++){
			scanf("%d%d",&num,&m);
			if(num==1)num=14;
			p[1][num]++;
		}
		shen=n;
		minn=100000;
		dfs(1);
		printf("%d\n",minn);
	}
}

标程:

#include<bits/stdc++.h>
using namespace std;
int T,n,ans,sum[25];
void dfs(int x)//x为出牌次数
{
	if (x>=ans) return;
	//顺子
	int k=0;//单顺子
	for (int i=3;i<=14;i++)//注意2和大小王不能考虑
	{
		if(sum[i]==0) k=0;//顺子断了
		else
		{
			k++;//顺子长度增加
			if(k>=5)//单顺子达到五张
			{
				for(int j=i;j>=i-k+1;j--) sum[j]--;//出牌
				dfs(x+1);//继续搜
				for(int j=i;j>=i-k+1;j--) sum[j]++;//回溯
			}
		}
	}
	k=0;//双顺子
	for(int i=3;i<=14;i++)
	{
		if(sum[i]<=1) k=0;
		else 
		{
			k++;
			if(k>=3)//双顺子达到三组
			{
				for(int j=i;j>=i-k+1;j--) sum[j]-=2;//出牌
				dfs(x+1);
				for(int j=i;j>=i-k+1;j--) sum[j]+=2;//回溯
			}
		}
	}
	k=0;//三顺子    //以下同理
	for(int i=3;i<=14;i++)
	{
		if(sum[i]<=2) k=0;
		else 
		{
			k++;
			if(k>=2)//三顺子达到两组
			{
				for(int j=i;j>=i-k+1;j--) sum[j]-=3;
				dfs(x+1);
				for(int j=i;j>=i-k+1;j--) sum[j]+=3;
			}
		}
	}
	//带牌
	for(int i=2;i<=14;i++)//枚举有3张或4张的牌(这样才能带牌)
	{
		if(sum[i]<=3)
		{
			if(sum[i]<=2) continue;//三张以下(不含三张)不能带牌
			sum[i]-=3;//出掉用来带别人的牌
			for(int j=2;j<=15;j++)//带单张
			{
				if(sum[j]<=0||j==i) continue;//没有牌怎么带??
				sum[j]--;//出掉被带的单张
				dfs(x+1);
				sum[j]++;//回溯
			}
			for(int j=2;j<=14;j++)//带一对
			{
				if(sum[j]<=1||j==i) continue;//没有一对怎么带?
				sum[j]-=2;//出掉被带的一对
				dfs(x+1);
				sum[j]+=2;//回溯
			}
			sum[i]+=3;//回溯
		} 
		else//大于3可以4带别的也可以3带别的
		{
			sum[i]-=3;//先用3张带别的
			for(int j=2;j<=15;j++) //带单张  //以下原理同上
			{
				if(sum[j]<=0||j==i) continue;
				sum[j]--;
				dfs(x+1);
				sum[j]++;
			}
			for(int j=2;j<=14;j++) //带一对
			{
				if(sum[j]<=1||j==i) continue;
				sum[j]-=2;
				dfs(x+1);
				sum[j]+=2;
			}
			sum[i]+=3;
			
			sum[i]-=4; //再用4张带别的 
			for(int j=2;j<=15;j++) //带2个单张
            {
				if(sum[j]<=0||j==i) continue;//自己不能带自己喽
				sum[j]--;//出被带的第一张单张牌
				for (int k=2;k<=15;k++)//找第二张单张
				{
					if(sum[k]<=0||j==k) continue;
					sum[k]--;//出被带的第二张单张牌
					dfs(x+1);
					sum[k]++;//回溯
				}
				sum[j]++;//回溯
			}
			for(int j=2;j<=14;j++)//带2个对儿
			{
				if(sum[j]<=1||j==i) continue;
				sum[j]-=2;//出被带的第一对牌
				for(int k=2;k<=14;k++) 
				{
					if(sum[k]<=1||j==k) continue;
					sum[k]-=2;//出被带的第二对牌
					dfs(x+1);
					sum[k]+=2;//回溯
				}
				sum[j]+=2;//回溯
			}
			sum[i]+=4;//回溯
		}
	}
	//把剩下的牌出完
	for(int i=2;i<=15;i++) if(sum[i]) x++;
	ans=min(ans,x);
}
int main() 
{
	scanf("%d%d",&T,&n);
	while(T--)
	{
		ans=0x7fffffff;//搞大一点
		int x,y;
		memset(sum,0,sizeof sum);//多次询问,记得清零
		for(int i=1;i<=n;i++)
		{
			scanf("%d%d",&x,&y);
			if (x==0) sum[15]++;//把两张王存在一起(但是带牌的时候注意不要做对儿)
			else if(x==1) sum[14]++;//由于A的牌值大所以往后放
		    else sum[x]++;//其他牌存在相应位置
		}
		dfs(0);//开始暴搜
		printf("%d\n",ans);
	}
}

估分:20
实际得分:30
反思:搜索优化不可少。

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值