SCAU2020春季个人排位赛div2 #1——题解

这一场的排名是2,然而并没有什么卵用。
//头文件如下,ac代码全部省略头文件

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <algorithm>
#include <queue>
#include <deque>
#include <cstring>
#include <string>
#include <iostream>
#include <set>
#define ll long long
#define maxn 101000
#define mod 100000007
#define inf 0x3f3f3f3f
using namespace std;

*A题hdu2544

(不会做,事后学了Dijkstra算法,明天用floyd再写一遍)
题意:题目给出n,m分别为路口数量(1~n)和街道数量,街道包含三个元素:路口a,路口b,走过这条街道用的时间c,求问从路口1去到路口n最少需要多长时间。
题解:dijkstra套一套就好啦
ac代码:

int way[150][150],len[150],poi[150],n,m;
//way储存两路口之间的路,len是某个路口到路口1的距离,
//poi用来记录某路口是否被标记
int dijkstra(int n,int m)
{
    for(int i=1;i<=n;i++)//初始化len
    {
        len[i]=way[i][1];
    }
    for(int i=1;i<=n-1;i++)
    {
        int minn=inf,u;
        for(int j=1;j<=n;j++)
        {
            if(poi[j]==0&&len[j]<minn)
            {
                minn=len[j];
                u=j;
            }
        }
        poi[u]=1;
        for(int j=1;j<=n;j++)
        {
            if(poi[j]==0&&(len[u]+way[u][j]<len[j]))
                len[j]=len[u]+way[u][j];
        }
    }
    return len[n];
    }
    int main()
{
    #ifdef local
    freopen("in.txt", "r", stdin);
    #endif // local
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)break;
        for(int i=1;i<=n;i++)
        {
            poi[i]=0;
            for(int j=1;j<=n;j++)
                if(i==j)way[i][j]=0;
            else way[i][j]=inf;
        }
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            if(w<way[u][v])way[u][v]=way[v][u]=w;
        }
        int ans=dijkstra(n,m);
        printf("%d\n",ans);
    }
 return 0;
}

B题CSU - 1803

题意: 给出m和n,求满足条件:1:1≤a≤n,1≤b≤m;2:a×b 是 2016 的倍数的a和b的组数
题解:利用同余定理,取n(m)和2016间比较小的一个进入循环,对于某个a(b),它的所有同类数x都满足x=a+n*2016(n是任意实数,则x%2016==a%2016,因此可得
ac代码:

int main()
{
   #ifdef local
   freopen("in.txt", "r", stdin);
   #endif // local
   int n,m;
   while(scanf("%d%d",&n,&m)!=EOF)
   {
       ll ans=0;
       for(int i=1;i<=min(n,2016);i++)
       {
           for(int j=1;j<=min(m,2016);j++)
           {
               if((i*j)%2016==0)
               {
                   ll a=n/2016,b=m/2016;
                   if(n%2016>=i)a++;
                   if(m%2016>=j)b++;
                   ans+=a*b;
               }
           }
       }
       printf("%lld\n",ans);
   }
   return 0;
}

C题究极水题

题意:给你一组数据,可以去掉任意一个数,求最大值和最小值的最小差
题解:原最大-新最小,新最大-原最小,取比较小的一个就好
ac代码:

int k[101000];
int main()
{
    #ifdef local
    freopen("in.txt", "r", stdin);
    #endif // local
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&k[i]);
    }
    sort(k,k+n);
    int a=k[n-1]-k[1],b=k[n-2]-k[0];
    printf("%d\n",min(a,b));
	return 0;
}

D题HDU5965

题意:给你一个3*n矩阵,第一行和第三行每个格子最多可以放一个地雷,第二行没有地雷,第二行每个格子显示一个数字,代表以该格为中心,周围8个格子的地雷总和
题解:这是个dp题,第一列的埋地雷情况会影响后续n-1列的情况,每一列可以埋地雷数为0,1,2,对应情况数为1,2,1;
令n[i]为每一列的地雷数,sum[i]为每一列的第二行记录的九宫格地雷总数:通过画图,我们可以发现,n[i]=sum[i-1]-n[i-1]-n[i-2](用别的表达方式也可以,是这个意思就行)
因此,只要枚举第一列地雷数为0,1,2的情况即可,中间要加上条件判断,防止数据有坑。
PS:记得模一下

char str[10100];
int s[10100],lie[10100];
int main()
{
    #ifdef local
    freopen("in.txt", "r", stdin);
    #endif // local
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",str);
        int n=strlen(str);
        for(int i=0;i<n;i++)
          s[i+1]=str[i]-'0';
          //for(int i=1;i<=n;i++)printf("%d\n",s[i]);
        s[0]=lie[0]=0;
        ll ask=0;
        for(int i=0;i<=2;i++)
        {
            if(i>s[1])break;
            lie[1]=i;
            int j;
            for(j=2;j<=n;j++)
            {
                int a=s[j-1]-lie[j-1]-lie[j-2];
                if(a>2||a<0)break;
                lie[j]=a;//printf("**%d**%d\n",lie[j],j);
            }

            if(j<=n)continue;
            if(s[n]!=lie[n-1]+lie[n])continue;

            ll ans=1;
            //for(int j=1;j<=n;j++)printf("*%d\n",s[j]);
            for(int j=1;j<=n;j++)
            {
                if(lie[j]==0||lie[j]==2)ans=ans%mod;
                else ans=(ans*2)%mod;//printf("*%d\n",s[j]);
                //printf("**%lld--%d\n",ans,j);
            }
            ask=(ask+ans)%mod;//printf("**%lld\n",ask);

        }
        printf("%lld\n",ask);
    }
	return 0;
}

E题字符串题

题意:先给你一行句子,里面是各种动物的叫声,接下来告诉你除了狐狸以外所有动物的叫声,输出狐狸的叫声
题解:储存各种动物的叫声,与句子里的单词比较,进行删减
PSSSSSSSSSS:不要再把memset写成menset了!!!!!!!

char re[110][110];
int main()
{
    #ifdef local
    freopen("in.txt", "r", stdin);
    #endif // local
    int n;
    scanf("%d",&n);//printf("%d",n);
    while(n--)
    {
        getchar();
        memset(re,0,sizeof(re));
        char ch;
        int i=0,j=0,mark[120]={0};
        while((ch=getchar())!='\n')
        {
            if(ch!=' ')
            {
                re[i][j]=ch;
                j++;
            }
            else {i++;j=0;}
            //printf("%c",ch);
        }
        getchar();
        int n=i+1;
        while(1)
        {
            char a[120],b[120],c[120];
            scanf("%s %s %s",a,b,c);//printf("%s %s %s\n",a,b,c);
            if(!strcmp(a,"what")){scanf("%s %s",a,b);break;}
            for(i=0;i<n;i++)
            {
                if(!strcmp(c,re[i])){//printf("check_000\n");
                    memset(re[i],0,sizeof(re[i]));mark[i]=1;
                }
            }
        }
        for(i=0;i<n;i++)
        {
            if(mark[i]==0)
            {
                printf("%s",re[i]);
                if(i!=n-1)printf(" ");
            }
        }
        printf("\n");
    }
 return 0;
}
//训练的时候写不出来,很烦,我讨厌字符串
//下面的代码是看了颖贤的代码之后写的,之后搞一下stl再做一次

F题CF545d

题意:队伍里面有n个客人,每个客人需要的服务时间是xi,每个客人等待的时间是wi,如果wi>xi,那么客人会不高兴,否则客人满意,请问在整理队列之后最多能让几个客人满意
题解:排序,维护一个sum,对比
ac代码:

int k[101000];
int main()
{
    #ifdef local
    freopen("in.txt", "r", stdin);
    #endif // local
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&k[i]);
    }
    sort(k,k+n);
    int ans=1,sum=k[0];
    for(int i=1;i<n;i++)
    {
        if(k[i]>=sum)
        {
            ans++;
            sum+=k[i];
        }
    }
    printf("%d",ans);
	return 0;
}

G题hdu5877

防ak题,先存着,以后补。

H题hdu6187

题意:给出n个塔楼和m个墙,给出塔楼的位置和城堡的位置,每一个墙连接接两个塔楼,拆墙需要对应的花费围为wi,在城堡里的国王需要用最小的花费拆掉最少的墙,以到达领土的任意地方,也就是说塔不能形成环(城堡无论是否在环内,都必定有去不了的地方,所以坐标完全没用=-=),求国王最少要拆多少墙,拆墙的最小花费是多少
题解:去除最少的边,且边的权值和最小,对应的是最大生成树。那么根据拆墙代价排序,然后去成圈的墙就好了
ac代码:

int pre[101000];
int found(int x)
{
    int r=x;
    while(r!=pre[r])
        r=pre[r];
    int i=x,j;
    while(i!=r)
    {
        j=pre[i];
        pre[i]=r;
        i=j;
    }
    return r;
}
bool uno(int x,int y)
{
    int fx=found(x),fy=found(y);
    if(fx!=fy){
        pre[fx]=fy;return true;
    }
    else return false;
}
struct ppp
{
    int a,b,c;
}poi[205000];
bool cmp(ppp x,ppp y)
{
    return x.c>y.c;
}
int main()
{
    #ifdef local
    freopen("in.txt", "r", stdin);
    #endif // local
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        //printf("一开始%d %d\n",n,m);
        int x,y,cnt=0;
        ll sum=0;
        for(int i=1;i<=n;i++){pre[i]=i;scanf("%d%d",&x,&y);//printf("---%d %d\n",x,y);
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&poi[i].a,&poi[i].b,&poi[i].c);//printf("**%d %d %d\n",poi[i].a,poi[i].b,poi[i].c);
        }
        sort(poi+1,poi+1+m,cmp);//for(int i=1;i<=m;i++)printf("**%d %d %d\n",poi[i].a,poi[i].b,poi[i].c);
        for(int i=1;i<=m;i++)
        {
            if(!uno(poi[i].a,poi[i].b))
            {
                sum=sum+poi[i].c;//printf("%d %d %d\n",i,m-cnt,poi[i].c);
            }
            else cnt++;
        }
        printf("%d %lld\n",m-cnt,sum);
    }
	return 0;
}

收获:学了Dijskstra算法,学了最大生成树,没了。
今天也要加油ovo

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值