2021-10-05国庆集训模拟赛


1、寻找道路

思路:标记所有无法到达终点的子点的父点,然后搜索和这题杠了一天,不停地修改,然后它又不停地陷入死循环最终改完后时间超限好难受
估分:20
实得:30
代码:

#include<bits/stdc++.h>
using namespace std;
bool inroad[10010],can[10010];      
int dis[10010];                     
vector<int>side[10010];               
vector<int>edis[10010];              
int main(){
    int n,m,a,b,s,t;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>a>>b;
        side[a].push_back(b);
        edis[b].push_back(a);
    }
    cin>>s>>t;
    can[t]=1;                        
    queue<int>que; 
    que.push(t);
    while(!que.empty()){
        int now=que.front();
        que.pop();
        for(int i=edis[now].size()-1;i>=0;i--){
            int to=edis[now][i];
            if(!can[to]){
                que.push(to);   
                can[to]=1;
            }
        }
    }
    if(!can[s]){
        cout<<"-1";
        return 0;
    }
    for(int i=1;i<=n;i++){
        if(can[i]){
            inroad[i]=1;
            for(int j=side[i].size()-1;j>=0;j--){
                int to=side[i][j];
                if(!can[to]){
                    inroad[i]=0;
                    break;
                }
            }
        }
    }
    if(!inroad[s]){
    	cout<<"-1";
    	return 0;
        }
    dis[s]=1;que.push(s);
    while(!que.empty()){
        int now=que.front();
        que.pop();
        if(now==t){
            cout<<dis[t]-1;
            return 0;
        }
        for(int i=side[now].size()-1;i>=0;i--){
            int to=side[now][i];
            if(inroad[to]&&!dis[to]){
                dis[to]=dis[now]+1;
                que.push(to);
            }
        }
    }
    cout<<"-1";   
	return 0;                  
}

正解(洛谷):

#include<bits/stdc++.h>
using namespace std;
bool inroad[10010],can[10010];      
int dis[10010];                     
vector<int>side[10010];               
vector<int>edis[10010];              
int main(){
    int n,m,a,b,s,t;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>a>>b;
        side[a].push_back(b);
        edis[b].push_back(a);
    }
    cin>>s>>t;
    can[t]=1;                        
    queue<int>que; 
    que.push(t);
    while(!que.empty()){
        int now=que.front();
        que.pop();
        for(int i=edis[now].size()-1;i>=0;i--){
            int to=edis[now][i];
            if(!can[to]){
                que.push(to);   
                can[to]=1;
            }
        }
    }
    if(!can[s]){
        cout<<"-1";
        return 0;
    }
    for(int i=1;i<=n;i++){
        if(can[i]){
            inroad[i]=1;
            for(int j=side[i].size()-1;j>=0;j--){
                int to=side[i][j];
                if(!can[to]){
                    inroad[i]=0;
                    break;
                }
            }
        }
    }
    if(!inroad[s]){
    	cout<<"-1";
    	return 0;
        }
    dis[s]=1;que.push(s);
    while(!que.empty()){
        int now=que.front();
        que.pop();
        if(now==t){
            cout<<dis[t]-1;
            return 0;
        }
        for(int i=side[now].size()-1;i>=0;i--){
            int to=side[now][i];
            if(inroad[to]&&!dis[to]){
                dis[to]=dis[now]+1;
                que.push(to);
            }
        }
    }
    cout<<"-1";   
	return 0;                  
}

2、国王游戏

和第一题杠了一天的我啥都不说,直接上洛谷正解

#include<cstdio>
#include<algorithm>//用到sort
#include<cstring>//用到memset
using namespace std;
const int MAXN=1010,MAXM=10010;//注意高精数组开到10000
struct Node{//一个人
	int l,r;
}a[MAXN];
int pro[MAXM],ans[MAXM],tmp[MAXM];//左手乘积,答案,临时数组
int read(){//快读
	int x=0,f=1;//记录数和符号
	char c=getchar();//读入字符
	while(c<'0'||c>'9'){//只要不是数
		if(c=='-') f=-1;//是负号就记录
		c=getchar();
	}
	while(c>='0'&&c<='9'){//只要是数
		x=x*10+c-'0';//挪位再加
		c=getchar();
	}
	return x*f;//返回数乘符号
}
bool cmp(Node aa,Node bb){//排序的比较函数
	return aa.l*aa.r<bb.l*bb.r;//按左右手数的乘积从小到大
}
void copy(int *aa,int *bb){//复制
	for(int i=0;i<MAXM;i++) aa[i]=bb[i];
}
bool more(int *aa,int *bb){//比较
	for(int i=MAXM-1;i>=0;i--){
		if(aa[i]>bb[i]) return 1;
		if(aa[i]<bb[i]) return 0;
	}
	return 0;//注意这里也要写上,写0写1随便
}
void times(int *aa,int num){//乘法
	for(int i=MAXM-2;i>=0;i--) aa[i]*=num;//先乘
	for(int i=0;i<MAXM-1;i++){//再进位
		aa[i+1]+=(aa[i]/10);//先加前一位
		aa[i]%=10;//在处理这一位
	}
}
void div(int *aa,int *bb,int num){//除法
	memset(bb,0,sizeof(bb));//赋为0
	int x=0;
	for(int i=MAXM-1;i>=0;i--){//从高位到低位
    	x=x*10+aa[i];//挪位再加
		bb[i]=x/num;//记录
		x%=num;//模上
	}
}
void print(int *aa){//输出
	bool flag=0;//记录是否能输出
	for(int i=MAXM-1;i>=0;i--){
		if(!flag){//如果不能
			if(aa[i]) flag=1;//找到第一个不是0的位,可以输出了
			else continue;//还是不能
		}
		printf("%d",aa[i]);//输出,不用空格或换行
	}
}
int main(){//主函数
	int n=read();
	for(int i=0;i<=n;i++) a[i].l=read(),a[i].r=read();
	sort(a+1,a+n+1,cmp);//排序
	pro[0]=1;//注意乘积数组初始值为1
	for(int i=0;i<=n;i++){//注意从0开始,国王
		div(pro,tmp,a[i].r);//先除到tmp上
		if(more(tmp,ans)) copy(ans,tmp);//比较,满足就复制
		times(pro,a[i].l);//自乘
	}
	print(ans);//输出
	return 0;//华丽结束
}

3、书柜的尺寸

无奈上正解代码(洛谷)

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <utility>
#define min(a,b) (a>b?b:a)
void MINE(unsigned short&a,int b)
{a=min(a,b);}
int max(int a,int b)
{return a>b?a:b;}
#define LNG    2200
unsigned short DPM[LNG+1][LNG+1];
unsigned short Last[LNG+1][LNG+1];
int N,Sum;
std::pair<int,int> Dat[80];
int LSum[80];
void Input()
{
    scanf("%d",&N);
    int wi;
    for(wi=1;wi<=N;++wi)
    {
        scanf("%d %d",&Dat[wi].first,&Dat[wi].second);
        Dat[wi].first=(-Dat[wi].first);
        Sum+=Dat[wi].second;
    }
    std::sort(Dat+1,Dat+1+N);
    for(wi=1;wi<=N;++wi)
        Dat[wi].first=-Dat[wi].first;
    for(wi=1;wi<=N;++wi)
        LSum[wi]=LSum[wi-1]+Dat[wi].second;
}
void DPA()
{
    int wi,wia,wib;
    int nh,nl,ns;
    memset(Last,0x3F,sizeof(Last));
    memset(DPM,0x3F,sizeof(DPM));
    Last[0][0]=0;
    for(wi=1;wi<=N;++wi)
    {
        nh=Dat[wi].first;
        nl=Dat[wi].second;
        ns=LSum[wi-1];
        for(wia=0;wia<=ns;++wia)
            for(wib=0;wib+wia<=ns;++wib)
                if(Last[wia][wib]^0x3F3F)
                {
                    if(!wia)
                        MINE(DPM[nl][wib],Last[0][wib]+nh);
                    else
                        MINE(DPM[wia+nl][wib],Last[wia][wib]);
                    if(!wib)
                        MINE(DPM[wia][nl],Last[wia][0]+nh);
                    else
                        MINE(DPM[wia][wib+nl],Last[wia][wib]);
                    if(!(ns-wia-wib))
                        MINE(DPM[wia][wib],Last[wia][wib]+nh);
                    else
                        MINE(DPM[wia][wib],Last[wia][wib]);
                }
        memcpy(Last,DPM,sizeof(DPM));
        memset(DPM,0x3F,sizeof(DPM));
    }
}
int main()
{
    Input();
    DPA();
    int wia,wib;
    int ans=0x3FFFFFFF;
    for(wia=1;wia<=Sum;++wia)
        for(wib=1;wib<=Sum;++wib)
            if(Sum-wia-wib)
                if(Last[wia][wib]^0x3F3F)
                    if(ans>max(wia,max(wib,Sum-wia-wib))*Last[wia][wib])
                        ans=max(wia,max(wib,Sum-wia-wib))*Last[wia][wib];
    printf("%d\n",ans);
    return 0;
}

 

4、

正解不会打无助
转移部分核心代码

dp[0]=0;
 int now=idx(s[0]);
 dp[now]=1;
 for (int i=1;i<n;i++){
      now^=idx(s[i]);
      for (int j=0;j<=25;j++){
            if ((now^(1<<j))!=now)
            dp[now]=min(dp[now],dp[now^(1<<j)]+1);
      }
 }
 if (now==0) dp[now]=1;
 printf("%d\n",dp[now]);

反思

和第一题杠了一天的我瑟瑟发抖~~以后不能再盯着一题杠了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熙筠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值