BestCoder Round #68 (div.1)

4 篇文章 0 订阅
2 篇文章 0 订阅

做的 比较屎,但是还是涨rating了。。。

1001. HDU 5611 Baby Ming and phone number 

http://acm.hdu.edu.cn/showproblem.php?pid=5611

直接按题意模拟,需注意以下闰年的判断方法(普通年,世纪年)  

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std;

typedef long long LL;

char s[12];

int yes(int n,int y,int r){
    if(y==0||y>12) return 0;
    if(y==1||y==3||y==5||y==7||y==8||y==10||y==12){
        if(r<=31)  return 1;
        return 0;
    }
    if(y!=2){
        if(r<=30) return 1;
        return 0;
    }
    if(n%4==0){
        if(n%100==0){
            if(n%400==0){
                if(r<=29)  return 1;
                return 0;
            }
            else{
                if(r<=28)  return 1;
                return 0;
            }
        }
        else{
            if(r<=29)  return 1;
            return 0;
        }
    }
    if(r<=28)  return 1;
    return 0;
}

int main (){
    int t,n,a,b;
    scanf("%d",&t);
    int ll=19800101,rr=20161231;
    while(t--){
        scanf("%d%d%d",&n,&a,&b);
        LL ans=0;
        while(n--){
            //cout<<ans<<endl;
            scanf("%s",s);
            if(s[6]==s[7]&&s[7]==s[8]&&s[8]==s[9]&&s[9]==s[10]){
                ans=ans+a;
                continue;
            }
            if((s[6]-s[7]==1)&&(s[7]-s[8]==1)&&(s[8]-s[9]==1)&&(s[9]-s[10]==1)){
                ans=ans+a;
                continue;
            }
            if((s[6]-s[7]==-1)&&(s[7]-s[8]==-1)&&(s[8]-s[9]==-1)&&(s[9]-s[10]==-1)){
                ans=ans+a;
                continue;
            }
            int kk=0;
            int n;
            int y=(s[7]-'0')*10+(s[8]-'0');
            int r=(s[9]-'0')*10+(s[10]-'0');
            for(int i=3;i<=10;i++){
                kk=kk*10+s[i]-'0';
                if(i==6)  n=kk;
            }
            if(kk<=rr&&kk>=ll&&yes(n,y,r)){
                ans=ans+a;
                continue;
            }
            ans=ans+b;
        }
        cout<<ans<<endl;
    }
    return 0;
}

1002.HDU 5612 Baby Ming and Matrix games 

http://acm.hdu.edu.cn/showproblem.php?pid=5612

题意:在一个n*m的矩阵中行数和列数均为偶数的格点上有0~9之间的数字,数字之间的格点上有四则运算的符号,在矩阵上画一条不与自己相交的线,要求能形成一个合法的运算表达式,问你能否找到这样一个表达式使运算结果为给定值sun(-1e18~1e18)。另外每个矩阵上的数字个数不超过15个。

解法:比赛时候想的是状态压缩DP,将矩阵中的数字编号,dp【s】【i】表示数字集合s构成的、以第i个数字结尾的表达式的结果的集合,对于与 i 相邻的编号为 j 的数字,如果(s&(1<<j))==0,dp【s|(1<<j)】【j】=dp【s】【i】(ope)num【j】,其中ope为i与j之间的四则运算,num【j】为第j个数字的值。但是TLE。。。

其实想一想是有道理的,解题的关键是路径构成表达式,强行用集合表示肯定会TLE,因为会多出很多冗余的状态、还需要维护集合。

看题解,发现就是一个裸的DFS,比赛时候想过但是过高地估计了复杂度,题解上说数字个数不超过15个最多有14000个状态(不知道咋算的),直接dfs就好。另外运算结果可能出现小数,但是这个题数据比较菜,用double表示结果都能过(需要用eps控制精度)。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std;

typedef long long LL;
typedef double LD;

const LD eps=1e-10;

char s[50][50];
int vis[50][50];

int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};

int t,n,m,Get;
LL sum;

int OK;
LD ope(LD a,LD b,char c){
    if(c=='+')  return a+b;
    if(c=='-')  return a-b;
    if(c=='*')  return a*b;
    if(fabs(b)<=eps)  {
        OK=0;
        return -1;
    }
    return a/b;
}

void dfs(LD now,int x,int y){
    if(Get)  return ;
    vis[x][y]=1;
    if(fabs(now-(LD)sum)<=eps){
        Get=1;
        return ;
    }
    for(int i=0;i<4;i++){
        int xx=x+dx[i]*2,yy=y+dy[i]*2;
        if(xx<n&&xx>=0&&yy<m&&yy>=0&&vis[xx][yy]==0){
            OK=1;
            LD New=ope(now,s[xx][yy]-'0',s[x+dx[i]][y+dy[i]]);
            if(OK)  dfs(New,xx,yy);
        }
    }
    vis[x][y]=0;
    return ;
}

int main (){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        cin>>sum;
        for(int i=0;i<n;i++)  scanf("%s",s[i]);
        Get=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(s[i][j]>='0'&&s[i][j]<='9'){
                    memset(vis,0,sizeof(vis));
                    dfs(s[i][j]-'0',i,j);
                }
                if(Get)  break;
            }
            if(Get)  break;
        }
        if(Get)
            printf("Possible\n");
        else
            printf("Impossible\n");
    }
    return 0;
}

1003. HDU 5613 Baby Ming and Binary image 

http://acm.hdu.edu.cn/showproblem.php?pid=5613

题意:就是给你一个n*m(n<=12,m<=100)的矩阵,让你恢复出他的原矩阵。原矩阵到现矩阵的方式为:其原矩阵为01矩阵,且原矩阵第一行和最后一行均为0,将其每个位置的值变为其本身和周围八个位置一共九个位置上1的个数。

解法:注意到n的个数很小,且只要知道了原矩阵第一列的01分布就可以根据给出的矩阵复原出原矩阵,再验证一下最后一列是否符合要求即可。那么我们就可以暴力枚举2^(n-2)种可能个第一列的01分布,然后逐个验证即可。(赛后改题时候出了很多细小的错误,还是练得少啊)。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std;

int a[15][120],b[15][120],ans[15][120];
int n,m;

void print(int s){
    for(int i=0;i<11;i++){
        if(s&(1<<i))  printf("1");
        else printf("0");
    }
    printf("\n");
}

int solve(int s){
    //print(s);
    for(int i=0;i<n-2;i++){
        if(s&(1<<i))
            b[i+2][1]=1;
        else
            b[i+2][1]=0;
    }
    int tot;
    for(int j=2;j<=m;j++){
        for(int i=2;i<n;i++){
            tot=b[i-2][j-2]+b[i-2][j-1]+b[i-2][j]+
                b[i-1][j-2]+b[i-1][j-1]+b[i-1][j]+
                b[i][j-2]+b[i][j-1];
            if(tot==a[i-1][j-1])
                b[i][j]=0;
            else{
                if(tot==a[i-1][j-1]-1)
                    b[i][j]=1;
                else
                    return 0;
            }
        }
    }
   /* for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            printf("%d ",b[i][j]);
        printf("\n");
    }*/
    for(int i=1;i<=n;i++){
        tot=b[i-1][m-1]+b[i-1][m]+b[i][m-1]+b[i][m]+b[i+1][m-1]+b[i+1][m];
        if(tot!=a[i][m])  return 0;
    }
    return 1;
}

int main (){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&a[i][j]);
        int GET=0;
        memset(b,0,sizeof(b));
        for(int i=0;i<(1<<(n-2));i++){
            if(solve(i)){
                GET++;
                if(GET==1){
                    for(int j=1;j<=n;j++)
                        for(int k=1;k<=m;k++)
                            ans[j][k]=b[j][k];
                }
                if(GET>=2)  break;
            }

        }
        if(GET>0){
            if(GET>1)
                printf("Multiple\n");
            else{
                for(int i=1;i<=n;i++){
                    for(int j=1;j<m;j++)
                        printf("%d ",ans[i][j]);
                    printf("%d\n",ans[i][m]);
                }
            }
        }
        else
            printf("Impossible\n");
    }
    return 0;
}

1004. HDU 5614 Baby Ming and Matrix tree 

http://acm.hdu.edu.cn/showproblem.php?pid=5614

传说中的树链剖分,目前不会啊。。。。(留个坑)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值