衡阳八中noip2014模拟赛day1

来源:互联网 发布:mac任务管理器快捷键 编辑:程序博客网 时间:2024/04/26 10:32

衡阳八中noip2014模拟赛day1

T1国色天香

题目简要:给出火柴棒的根数,问拼出数字的最大最小值
解答:
火柴棒拼数字1 2 3 4 5 6 7 8 9 0
需要火柴棒 2 5 5 4 5 6 3 7 6 6
对于最大值,我们首先要保证最多的位数,即尽可能多的摆1(因为它需要的火柴棒数2最小),对于n%2==1的情况,我们只需将最高位改为7(需要3根)。
对于最小值,我们同样首先需要保证最小的位数,即尽可能的摆8(需要7根)。对于余下不同火柴棒的情况:
n%7==1
将最高位8换为10
n%7==2
在最高位前添加1
n%7==3
(1)n==3 最高位前添加7
(2)n==10 最高位8变为22
(3)n==17 最高位88变为200
n%7==4
(1)n==4 最高位前添加4
(2)n==11 最高位8变为20
n%7==5
最高位前添加2
n%7==6
最高位前添加6
附代码:

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>using namespace std;//2,5,5,4,5,6,3,7,6,6;void findmax(int x){    int m=x;    if(m&1)putchar('7'),m-=3;    for(;m;m-=2)putchar('1');    putchar(' ');    return;}void findmin(int x){    int m=x;    switch(m%7)    {        case 1:            putchar('1'),putchar('0');            m-=8;            break;        case 2:            putchar('1');            m-=2;            break;        case 3:            if(m==3)            {                putchar('7');                m-=3;            }            else if(m==10)            {                putchar('2'),putchar('2');                m-=10;            }            else            {               putchar('2'),putchar('0'),putchar('0');               m-=17;               }            break;        case 4:            if(m==4)            {                putchar('4');                m-=4;            }            else            {                putchar('2'),putchar('0');                m-=11;            }            break;        case 5:            putchar('2');            m-=5;            break;        case 6:            putchar('6');            m-=6;            break;    }    for(;m;m-=7)putchar('8');    putchar(10);    return;}int main(){    int T,x;    scanf("%d",&T);    while(T--)    {        scanf("%d",&x);        findmax(x);        findmin(x);    }    return 0;} 

T2无语凝噎

未完待续。。。
题解也看不懂怎么破。。好吧,我们来看第三题

T3福慧双修

其实不是完全搞懂了。有时间再做一遍。
吐槽一下,名字起的这么雷人真的好吗,剧情这么假真的好吗。。。
题目简要:给出一个无向图,每条边正向,反向需要的时间不同(这不就是有向图吗。。),且一条路只能通过一回,问从1回到1需要的最短时间。
题目解析:看完题目我的第一想法是建立一个新点当作终点,它的入/出度与1完全相同,但YY了一下发现很难保证每条边只走一遍。于是就跑去看题解啦。
题解是这样的,思路其实也是建立新点,但构图非常不同。
首先要跑一遍spfa,求出每一个点到1的最短距离dis[i],并记录prev[i]表示这条路径上与1相连的点的标号。然后——>注意前方高能。
枚举图中每一条边

Part1:该边为x连向1,边权为value。

(1)当prev[x]!=x说明从1到x的最短路并没有经过这条边,故在新图中建立一条从起点到终点的边,边权为value+dis[u]
(2)当prev[x]==x即不能再走该边,在新图中建立从x到终点的边,边权为value.

Part2:该边为从1连向x,边权为value

(1)当prev[x]=x,说明原图中即存在这样的最短边
(2)当prev[x]!=x,说明原点到达v的最短路径不是改边,故在新图中建立从1到x的边,边权为value.

Part3:该边的起点和终点均不为1.

(1)当prev[u]!=prev[v],说明原点到达两端点的最短路径是不同的,即存在一条从1到v,边权为dis[u]+value.
(2)当prev[u]==prev[v],在新图中保留原边。

最后在新图中求一次从1到n+1的最短路。
贴代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<queue>#define maxn 50048#define maxm 100003using namespace std;struct node{    int to,from,val,next;};node e[maxm*2],en[maxn*2];int head[maxn];int dis[maxn];int prev[maxn];bool vis[maxn];int tot,totn;int n,m;void add(int x,int y,int u){    e[++tot].to=y;    e[tot].from=x;    e[tot].val=u;    e[tot].next=head[x];    head[x]=tot;}void newadd(int x,int y,int u){    en[++totn].to=y;    en[totn].from=x;    en[totn].val=u;    en[totn].next=head[x];    head[x]=totn;}void spfa(){    memset(dis,0x7f7f7f7f,sizeof(dis));    memset(vis,0,sizeof(vis));    queue<int> Q;    Q.push(1);vis[1]=1;dis[1]=0;    while(Q.size())    {        int p=Q.front();Q.pop();        vis[p]=0;        for(int k=head[p];k;k=e[k].next)        {            int v=e[k].to;            if(dis[v]>dis[p]+e[k].val)            {                dis[v]=dis[p]+e[k].val;               if(p==1) prev[v]=v;                 else prev[v]=prev[p];               if(!vis[v])vis[v]=true,Q.push(v);            }            }    }}int main(){    scanf("%d%d",&n,&m);    tot=0;    int u,v,w,y;    memset(head,0,sizeof(head));    for(int i=0;i<m;i++)    {        scanf("%d%d%d%d",&u,&v,&w,&y);        add(u,v,w);        add(v,u,y);    }    spfa();    //½¨Á¢ÐÂͼ    totn=0;    for(int i=1;i<=n;i++)     for(int k=head[i];k;k=e[k].next)        {            if(e[k].to==1)            {               if(prev[i]==i)newadd(i,n+1,e[k].val);                else newadd(1,n+1,e[k].val+dis[i]);            }            else if(i==1)            {               int v=e[k].to;               if(prev[v]==v)continue;               newadd(1,v,e[k].val);            }            else            {                int v=e[k].to;                if(prev[i]==prev[v])newadd(i,v,e[k].val);                else newadd(1,v,dis[i]+e[k].val);            }       }    //ÔÚԭͼÉÏÖØй¹½¨ÐÂͼ£¬ÖØÐÂÀûÓÃspfa()º¯Êý     tot=0;    memset(head,0,sizeof(head));    for(int i=1;i<=totn;i++)    {        int pu=en[i].to;        int pv=en[i].from;        int pw=en[i].val;        add(pv,pu,pw);    }    spfa();    int ans=dis[n+1];    if(ans==0x7f7f7f7f)ans=-1;    printf("%d\n",ans);    return 0;}
0 0
原创粉丝点击