BestCoder Round #14 hdu 5066 - 5069

A

#include<cstdio>

int main(){
    int a,b;
    while(~scanf("%d %d",&a,&b)){
        printf("%d\n",a+a-b);
    }
    return 0;
}


B  可以把点抽离出来,或者直接在50*50上bfs+dp。第一种复杂度更低

状态压缩+dp  当时可能想dp[S-1][0]一定是inf什么的,脑子抽了。  我trick能力几乎没有啊...

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define inf 0x3f3f3f3f
int n,m;
int a[52][52],dis[11][11];
int x[11],y[11],cnt;
int dp[1<<11][11];
int main(){
    while(cin>>n>>m){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            cin>>a[i][j];
        a[1][1]=1;
        cnt=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(a[i][j]) x[cnt]=i,y[cnt]=j,cnt++;
        for(int i=0;i<cnt;i++)
            for(int j=0;j<cnt;j++)
             dis[i][j]=abs(x[i]-x[j])+abs(y[i]-y[j]);
        int S=1<<cnt;
        memset(dp,inf,sizeof dp);
        dp[1][0]=0;
        for(int s=1;s<S;s++){
            for(int j=0;j<cnt;j++){
                if(dp[s][j]==inf) continue;
                for(int k=0;k<cnt;k++){//j to k
                    if(s&(1<<k)) continue;
                    dp[s|(1<<k)][k]=min(dp[s|(1<<k)][k],dp[s][j]+dis[j][k]);
                }
            }
        }
        int ans=inf;
        for(int i=0;i<cnt;i++)// my wa point i=1
            ans=min(ans,dp[S-1][i]+dis[i][0]);
        printf("%d\n",ans);
    }
    return 0;
}
/*
1 1
0
*/


C 题意是n层楼,每层有2个门到下一层的2个门,在同一层不能从 门1-门2

把一层楼看成一个点,a11 a12 表示第x层的门 i 到达下一层x+1的门 j 的情况数

                                   a21 a22

x-y的情况数就是x-y-1 的 矩阵乘

由于是动态更新,在线查询的,所以用线段树(dan)维护矩阵区间

开始没注意门编号是1或2,没-1,对于细节应该更细心。

//19--57 40min
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int MOD=1000000007,N=50005;
struct Mat{
    LL a[2][2];
    Mat(){
        memset(a,0,sizeof a);
    }
    void init(){
        a[0][0]=a[1][1]=a[0][1]=a[1][0]=1;
    }
    void unit(){
        a[0][0]=a[1][1]=1;
        a[0][1]=a[1][0]=0;
    }
    Mat operator * (Mat b){
        Mat c;
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
             c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j])%MOD;
        return c;
    }
};

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
Mat tree[N*4];

void push_up(int rt){
    tree[rt]=tree[rt<<1]*tree[rt<<1|1];
}
void build(int l,int r,int rt){
    if(l==r){
        tree[rt].init();
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    push_up(rt);
}

Mat query(int a,int b,int l,int r,int rt){
    //printf("%d %d %d %d %d--\n",a,b,l,r,rt);
    if(a<=l&&b>=r){
        return tree[rt];
    }
    Mat ret; ret.unit();
    int m=(l+r)>>1;
    if(a<=m) ret=ret*query(a,b,lson);
    if(b>m) ret=ret*query(a,b,rson);
    return ret;
}

void update(int x,int a,int b,int l,int r,int rt){
    if(l==r){
        tree[rt].a[a][b]^=1;
        return;
    }
    int m=(l+r)>>1;
    if(x<=m) update(x,a,b,lson);
    else update(x,a,b,rson);
    push_up(rt);
}

int n,m;
int main(){
    int x,a,b,op;
    while(cin>>n>>m){
        build(1,n-1,1);
        while(m--){
            scanf("%d",&op);
            if(op==0){
                scanf("%d %d",&a,&b);
                Mat ans=query(a,b-1,1,n-1,1);
                printf("%d\n",(ans.a[0][0]+ans.a[0][1]+ans.a[1][0]+ans.a[1][1])%MOD);
            }else{
                scanf("%d %d %d",&x,&a,&b);//my wa point  a,b 1-2 
                update(x,a-1,b-1,1,n-1,1);
            }
        }
    }
    return 0;
}
/*
one floor has two stairs. floor 1 to floor n has (n-1)*2 stairs.
be careful about -1
*/



D 官方说是AC自动机,看几个A了的 好像是hash字符串的处理,以后补

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值