2015 Multi-University Training Contest 4--多校赛第四场--做完了再添加上来

来源:互联网 发布:python主要用来干什么 编辑:程序博客网 时间:2024/04/20 14:28

1001>HDU 5327  Olympiad

题意:计算[L,R]区间中满足个十百千...等这些位上面的数字没有重复的数字的个数,比如11的个位和十位都是1,这是重复了,所以不满足条件,123个十百位分别是1,2,3,没有重复,所以满足条件

PS:别想太复杂,判断一个数是否满足条件就把每个位的数字取出来用hash表查看重复,当然我用深搜类似于数位DP的方法一个数一个数的拼接起来打表。

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define Max(a,b) (a>b?a:b)#define Min(a,b) (a<b?a:b)using namespace std;int s[111111],vis[11];void dfs(int x,int l)//x记录当前拼接出来的数字,l用来区别是否可以添加0{    if(x>100000)return;    s[x]=1;    int i;    for(i=l;i<10;i++)    if(vis[i]==0)    {        vis[i]=1;        dfs(x*10+i,0);//除了拼接数字,除了拼接首位,其他都可以添加0        vis[i]=0;    }}int main (void){    int i,j,k,l,r,n;    memset(s,0,sizeof(s));    memset(vis,0,sizeof(vis));    dfs(0,1);//从首位开始拼接    for(i=1;i<=100000;i++)    s[i]+=s[i-1];    scanf("%d",&n);    while(n--&&scanf("%d%d",&l,&r))    {        printf("%d\n",s[r]-s[l-1]);    }    return 0;}

 

1002>HDU 5327 Problem Killer

题意:求输入序列的最长等差或等比的子序列,要求子序列是连续的

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define Max(a,b) (a>b?a:b)#define Min(a,b) (a<b?a:b)#define LL long longusing namespace std;LL s[1111111];int main (void){    LL t,n,i,j,k,l,r,dz,dm,rl,dl,rf,df;    scanf("%lld",&t);    while(t--)    {        scanf("%lld",&n);        r=dz=dm=-1;        rf=df=0;        rl=dl=l=1;        for(i=0;i<n;i++)        {            scanf("%lld",&s[i]);            if(i>0)//从第二个开始操作            {                if(rf==0)//是否第一次操作等差数列                {                    rf=1;                    r=s[i]-s[i-1];//获取公差                    rl=2;//标记长度                }else                {                    k=s[i]-s[i-1];//获取公差                    if(k==r)rl++;//查看是否公差一致                    else                    {                        l=Max(l,rl);//不一致则标记最长长度                        rl=2;//初始化长度                        r=k;//初始化公差                    }                }                if(df==0)是否第一次操作等比数列                {                    df=1;                    dz=s[i];                    dm=s[i-1];                    dl=2;                }                else                {                    if(dz*s[i-1]==dm*s[i])dl++;//同上,但是这里最好用乘法,因为除法会有精度损失                    else                    {                        l=Max(l,dl);                        dl=2;                        dz=s[i];                        dm=s[i-1];                    }                }            }        }        printf("%lld\n",Max(dl,Max(rl,l)));    }    return 0;}

 

1009>HDU 5335 Walk Out

题意:给你个0/1矩阵,从左上角走到右下角得到一个二进制数,这个数由路径上的0/1组成,要你求得到的二进制数最小是多少。

PS:二进制数的大小首先由有效长度决定,越短越小,然后相同长度则是从高往低找第一个不同的数字,这个数字越小则二进制数越小,**前导零不算有效数字。

所以在这里可以从左上角开始找到一个或者一堆距离右下角最近的点,这是保证有效数字更少,然后从这些点往右往下找传递,在保证距离缩短的同时,当距离相同,有map的值等于0出现则舍弃map的值等于1的那条路,因为在相同长度上,这个位的数字1已经大于0了

***要用广搜,深搜会溢出,因为深搜不能及时释放内存

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#define Max(a,b) (a>b?a:b)#define Min(a,b) (a<b?a:b)#define LL long long#define MAX 999999999using namespace std;int n,m,len;char map[1111][1111];int vis[1111][1111];int dd[4][2]={{1,0},{-1,0},{0,1},{0,-1}};struct node{    int x,y;}ss[111111];int bfs()//用广搜来普及所有与(0,0)在一堆的map1=0的点,并且标记好{    int i,j,k,l,x,y,xx,yy,top,back;    top=back=0;    k=0;    ss[top].x=ss[top].y=0;    top++;    while(top!=back)    {        x=ss[back].x;        y=ss[back].y;        back++;        if(back>=111111)back=0;        if(map[x][y]=='1')continue;        for(i=0;i<4;i++)        {            xx=x+dd[i][0];            yy=y+dd[i][1];            if(xx>=0&&yy>=0&&xx<n&&yy<m&&vis[xx][yy]==0)            {                vis[xx][yy]=1;                k=Max(k,xx+yy);                ss[top].x=xx;                ss[top].y=yy;                top++;                if(top>=111111)top=0;            }        }    }    return k;//返回的是距离(0,0)最远的点到(0,0)的距离,距离=x+y}int main (void){    int t,i,j,k,l,f1,f2,x,y;    scanf("%d",&t);    while(t--&&scanf("%d%d%*c",&n,&m))    {        memset(vis,0,sizeof(vis));        for(i=0;i<n;i++)        gets(map[i]);        vis[0][0]=1;        k=bfs();        if(k==n+m-2&&map[n-1][m-1]=='0')        {//如果最大距离到达了右下角,而右下角的map是1,则直接特判            puts("0");            continue;        }        l=n+m-2;        f1=1;//f1记录上一位操作中记录当前位的最优的数字        for(;k<=l;k++)//用距离来表示二进制数的位        {            f2=1;//f2是标记当前位的最优数字            for(x=0;x<n;x++)//遍历所有x            {                y=k-x;//用x求出y                if(x>=0&&y>=0&&x<n&&y<m)//判断是否过界                if(vis[x][y]==1&&map[x][y]-48<=f1)//判断是否是上一位用到了,并判断当前数字是否可取                {//关于map[x][y]-48<=f1,如果当前位有map=0的出现,则f1=0,可以排除掉所有的map=1
//如果当前位没有map=0的出现,则f1=1,会将所有map=1选择                    if(x<n-1)//往下走                    {                        vis[x+1][y]=1;//标记这个位置被用到                        if(map[x+1][y]=='0')f2=0;//标记是否有0可取                    }                    if(y<m-1)/往右走                    {                        vis[x][y+1]=1;                        if(map[x][y+1]=='0')f2=0;                    }                }            }            printf("%d",f1);//每操作完一位就输出一位            f1=f2;//把当前标记递给f1        }        printf("\n");    }    return 0;}

 

1010>HDU 5336  XYZ and Drops

题意:就是十滴水的游戏,水滴在大于4会分裂,给你r X c的地图,n个初始水滴,还有限制时间t,最后会给一个坐标(x,y)表示游戏开始时这个点默认为水滴分裂,要你求出t时间过后n个水滴的状态,存在就输出 "1 水滴大小",不存在就输出 "0 分裂时间"

PS: 这题不算难,是简化版的十滴水游戏,要注意的是分裂后产生的水滴只会在碰到初始水滴(即输入的n个位置上的水滴)才会停下来并融入,多个水滴同时融入一个初始水滴会叠加后分裂,比如两个水滴同时进入一个大小为4的初始水滴,可以理解为水滴大小变成6然后分裂,分裂后移动的水滴互不影响,即使相遇也不会融合在一起,最后一点就是分裂时间是初始水滴满足大小大于4的那一瞬间

比如:

input

1 2 1 1

1 1 4

1 2

output

0 1

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#define Max(a,b) (a>b?a:b)#define Min(a,b) (a<b?a:b)#define LL long long#define MAX 999999999using namespace std;int map1[111][111],map2[111][111],n,m,t;int dd[4][2]={{-1,0},{1,0},{0,-1},{0,1}};struct node{    int x,y,time,f;}ss,s;int num[111][2];bool cmp(int x,int y){    return x>0&&y>0&&x<=n&&y<=m;}void bfs(){    int i,j,k,l,x,y,time;    scanf("%d%d",&x,&y);//输入默认水滴分裂位置    queue<node> q;    ss.x=x;//初始化    ss.y=y;    ss.time=0;    for(i=0;i<4;i++)//记录分裂后的四个水滴的方向    {        ss.f=i;        q.push(ss);//并且存入队列    }    map1[x][y]=0;//默认水滴分裂完毕后清空水滴大小    while(q.size())    {        ss=q.front();        q.pop();        if(ss.time>=t)return;//如果超过时间就结束(跳过),用错了,应该是用continue的,呵呵,懒得改了        ss.x+=dd[ss.f][0];//按照记录的方向移动并改变坐标        ss.y+=dd[ss.f][1];        time=ss.time+1;//改变时间        x=ss.x;        y=ss.y;        if(cmp(x,y))//判断是否越界        {            if(map1[x][y]>0)//有初始水滴存在            {                map1[x][y]++;//融入,大小+1                if(map1[x][y]>4)//如果大小大于4                {                    map2[x][y]=time;//记录初始水滴分裂时间                    map1[x][y]=0;//大小归零                    for(i=0;i<4;i++)//分裂成四个方向的小水滴                    {                        ss.f=i;                        ss.time=time;                        q.push(ss);//把四个方向都放入队列
//记住,放入时的状态为分裂的瞬间,只变方向,不变时间和位置                    }                }            }else            {//无初始水滴存在                if(map2[x][y]==time)continue;//如果初始水滴分裂时间和当前相等则跳过,表示当前点也融入后分裂                ss.time=time;                q.push(ss);            }        }    }}int main (void){    int T,i,j,k,l;    while(scanf("%d%d%d%d",&n,&m,&T,&t)!=EOF)    {        memset(map1,0,sizeof(map1));//记录当前位置的初始水滴大小        memset(map2,0,sizeof(map2));//记录当前位置水滴分裂时间        for(i=0;i<T;i++)        {            scanf("%d%d%d",&j,&k,&l);            map1[j][k]=l;//在map1中记录相应位置的初始水滴            num[i][0]=j;//记录每个初始水滴的位置            num[i][1]=k;        }        bfs();//开始玩游戏        for(i=0;i<T;i++)        {            j=num[i][0];            k=num[i][1];//cout<<"A"<<j<<" "<<k<<endl;            if(map1[j][k]==0)            {                printf("0 %d\n",map2[j][k]);            }else            {                printf("1 %d\n",map1[j][k]);            }        }    }    return 0;}

 

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 分期乐账号忘记了怎么办 外链多了影响网站排名怎么办 自粘墙纸有气泡怎么办 贴壁纸阴角不力怎么办 自贴墙纸有气泡怎么办 壁纸贴的有起泡怎么办 pos机连接主机失败怎么办 无线pos机连接主机失败怎么办 水墨晕染模板用不了怎么办 申请入驻饿了么失败怎么办 天猫流量大淘宝怎么办 拼多多商家不退款怎么办 苹果手机开流量显示e怎么办 苹果手机有服务流量打不开怎么办 苹果七plus流量打不开怎么办 苹果手机突然打不开流量怎么办 天猫商家迟迟不发货怎么办 苹果7开不开机了怎么办 苹果机黑屏了开不起来怎么办 美团收银机连不上网怎么办 6s换电池后黑屏怎么办 苹果上的软件打不开也删不掉怎么办 苹果手机打开软件打不开怎么办 苹果电脑下载的软件打不开怎么办 苹果手机下载的软件都打不开怎么办 苹7果屏幕黑屏怎么办 苹果6s手机打不开怎么办 苹果ipad密码输入打不开怎么办 苹果平板黑屏了打不开怎么办 苹果6sp电影商城打不开怎么办 苹果6应用商城打不开怎么办 游戏下载好了安装不上怎么办 苹果5s应用商店不见了怎么办 id被停用手机白板打不开怎么办 苹果6s下载不了软件怎么办 苹果下载的软件打不开怎么办 苹果6s下不了app怎么办 苹果手机因为闪退打不开了怎么办 天猫方糖坏了怎么办 天猫魔盒的遥控器坏了怎么办 天猫盒子没声音怎么办