hnust选拔赛2

/*

 

hnust各题的解题思路:

1002冠军:


题目要求确保某一位你的朋友成为冠军,那么只要用各个人的比赛情况建立一个有向图

,如果a胜b,就建立一点a->b的边,最后用所有朋友点遍历一次全图,如果所有的点都

被遍历了,那么冠军一定在朋友中,至于是哪一个朋友我们不知道,但是题目要求只要

一个朋友是冠军就可以了,所以此法可解;

 

1003套盒子:

 

这题是区域赛的一个原题型,可转化为一个匹配问题,设盒子套盒子为一个匹配过程,

因为一个盒子最多只能套一个盒子,所以盒子的匹配容量为1,因为最底下的盒子套不

到一个盒子,所以在所有的盒子匹配完后,统计盒子容量为0的个数即为这题的解;

 

1005密钥:

一个模拟题,直接用最长的字符串枚举密钥的长度就可以了,从小枚举到大,如果一旦

符合,即为最短的可能密钥;这题的关键在于用最长的字符串来枚举密钥,而不是用最

短的,因为有可能最短的枚举完了,都不符合长串的要求,可是因为当密钥大于明文的

长度时,多余的部分是不起作用的,所以可能用更长的密钥其实是可以的,以致有可能

造成误解;

 

1006做面包:

 

二维背包问题,对以前的均分两份的一维背包进行扩展,这里用F[a][b]表示在第一个

烤箱里用了a分钟,在第二个烤箱里用了b分钟,那么自然第三个烤箱里就用了sum-a-b

分钟,就在就对a,b在进行背包,因为sum<=1200,ti<=30,所以a,b<=430,因为取超过3

分之一后没意义,后面就是状态转移了,如下:
if(F[a][b]==1)
{
 F[a+ti][b]=1;
  F[a][b+ti]=1;
}
转移的时间复杂度为O(40*430*430);

最后对所有的F[a][b]等于1的进行遍历一遍,取最优值就可以了;


1010最少步 :

区间记忆化搜索:

枚举所有的区间翻转(ps:也有可能这个并不需翻转,那么自然这个区间的最小步自然就

为0了),并记忆每个区间的最小步,最后的dfs(0,len-1)的最小步即为题解,时间

复杂度O(n^3);

 

各题的代码如下:

*/

 

1002:

#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
struct edge
{
    int to,next;
}edge[210000];
int ant,head[110000];
void add(int a,int b)
{
    edge[ant].to=b;
    edge[ant].next=head[a];
    head[a]=ant++;
}
int frd[110000],vis[110000];
void bfs(int root)
{
    int i,to;
    queue <int> que;
    que.push(root);
    vis[root]=1;
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            to=edge[i].to;
            if(!vis[to])
            {
                vis[to]=1;
                que.push(to);
            }
        }
    }
}
int main()
{
    int n,k,m,i,a,b;
    while(scanf("%d%d%d",&n,&k,&m),n+k+m)
    {
        ant=0;
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
        for(i=1;i<=k;i++)
            scanf("%d",&frd[i]);
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
        }
        for(i=1;i<=k;i++)
            bfs(frd[i]);
        for(i=1;i<=n;i++)
            if(!vis[i])
                break;
        puts(i==n+1?"yes":"no");
    }
    return 0;
}


1003:

 

#include<stdio.h>
#include<string.h>
int vis[510],pre[510];
struct node
{
    int  x,y,h;
}num[510];
int n;
int judge(int x,int y)
{
    return num[x].x>num[y].x&&num[x].y>num[y].y&&num[x].h>num[y].h;
}
int find(int x)
{
    int i;
    for(i=1;i<=n;i++)
    {
        if(x!=i&&!vis[i]&&judge(x,i))
        {
            vis[i]=1;
            if(!pre[i]||find(pre[i]))
            {
                pre[i]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int i,sum;
    while(scanf("%d",&n),n)
    {
        for(i=1;i<=n;i++)
            scanf("%d%d%d",&num[i].x,&num[i].y,&num[i].h);
        sum=0;
        memset(pre,0,sizeof(pre));
        for(i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            sum+=find(i);
        }
        printf("%d\n",n-sum);
    }
    return 0;
}


 

1005:

 

#include<stdio.h>
#include<string.h>
char str[110],tem[110],std[110];
char str1[110][110],str2[110][110];
int judge(char *s1,char *s2,char *s3)
{
    int i,len=strlen(s2),j,k;
    for(i=0,j=0;i<len;i++)
    {
        if(s1[j])
        {
            tem[j]=s2[i]+s1[j]-'A';
            if(tem[j]>'Z')tem[j]-=26;
            if(tem[j]!=s3[i])return 0;
            j++;
        }
        else 
        {
            for(k=0;k<j;k++)
                s1[k]=tem[k];
            j=0;
            i--;
        }
    }
    return 1;
}
int main()
{
    int n,len,i,k,j,flag,t,g;
    while(scanf("%d",&n),n)
    {
        k=0;
        for(i=1;i<=n;i++)
        {
            scanf("%s%s",str1[i],str2[i]);
            len=strlen(str1[i]);
            if(len>k)
            {
                flag=i;
                k=len;
            }
        }
        for(i=1;i<=k;i++)
        {
            for(j=0;j<i;j++)
            {
                std[j]=str2[flag][j]-str1[flag][j]+'A';
                if(std[j]<'A')
                    std[j]+=26;
            }
            std[i]=0;
            for(g=0;g<i;g++)
                str[g]=std[g];
            str[i]=0;
            if(judge(str,str1[flag],str2[flag]))
                t=1;
            else t=0;
            for(j=1;t&&j<=n;j++)
            {
                for(g=0;g<i;g++)
                    str[g]=std[g];
                str[i]=0;
                if(!judge(str,str1[j],str2[j]))
                    t=0;
            }
            if(t==1)
                break;
        }
        if(i<=k)
        {
            printf("%s\n",std);
        }
        else puts("Impossible");
    }
    return 0;
}

 

1006:

 

#include<stdio.h>
 #include<string.h>
 int dp[520][520],sum,num[45];
 int main()
 {
     int n,i,k,j,v;
     while(scanf("%d",&n),n)
     {
         sum=0;
         for(i=1;i<=n;i++)
         {
             scanf("%d",&num[i]);
             sum+=num[i];
         }
         memset(dp,0,sizeof(dp));
         dp[0][0]=1;
         for(i=1;i<=n;i++)
         {
             for(j=sum/3+50;j>=0;j--)
             {
                 for(k=sum/3+50;k>=0;k--)
                 {
                     if(dp[j][k])
                     {
                         dp[j+num[i]][k]=1;
                         dp[j][k+num[i]]=1;
                     }
                 }
             }
         }
         k=1200;
         for(i=0;i<=sum/3+50;i++)
         {
             for(j=0;j<=sum/3+50;j++)
             {
                 if(dp[i][j])
                 {
                     v=i;
                     if(j>v)v=j;
                     if(sum-j-i>v)v=sum-i-j;
                     if(v<k)k=v;
                 }
             }
         }
         printf("%d\n",k);
     }
     return 0;
 }
 


 

1010:

 

#include<stdio.h>
#include<string.h>
 char s1[210],s2[210];
 int dp[210][210];
 int Min(int a,int b){return a<b?a:b;}
 int dfs(int s,int t)
 {
     char bef;
     int i,a,b;
     if(s>t)return 0;
     if(dp[s][t]!=-1)
         return dp[s][t];
     for(i=s;i<=t;i++)
         if(s1[i]!=s2[i])
             break;
     if(i<=t)
     {
         a=b=0;
         bef='c';
         for(i=s;i<=t;i++)
         {
             if(s2[i]!=bef)
             {
                 if(s2[i]=='A')
                     a++;
                 else b++;
             }
             bef=s2[i];
         }
         if(a<b)
             dp[s][t]=a+1;
         else dp[s][t]=b+1;
         for(i=s;i<=t-1;i++)
         {
             a=dfs(s,i)+dfs(i+1,t);
             dp[s][t]=Min(dp[s][t],a);
         }
     }
     else dp[s][t]=0;
     return dp[s][t];
 }
 int main()
 {
     int len,cas;
     scanf("%d",&cas);
     while(cas--)
     {
         scanf("%s%s",s1,s2);
         memset(dp,-1,sizeof(dp));
         len=strlen(s1);
         printf("%d\n",dfs(0,len-1));
     }
     return 0;
 }



 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值