vijos 1110小胖邮递员;bzoj 1210: [HNOI2004]邮递员

Description

Smith在P市的邮政局工作,他每天的工作是从邮局出发,到自己所管辖的所有邮筒取信件,然后带回邮局。他所管辖的邮筒非常巧地排成了一个m*n的点阵(点阵中的间距都是相等的)。左上角的邮筒恰好在邮局的门口。 Smith是一个非常标新立异的人,他希望每天都能走不同的路线,但是同时,他又不希望路线的长度增加,他想知道他有多少条不同的路线可走。【任务描述】你的程序需要根据给定的输入,给出符合题意的输出:? 输入包括点阵的m和n的值;? 你需要根据给出的输入,计算出Smith可选的不同路线的总条数;

Input

只有一行。包括两个整数m, n(1 <= m <= 10, 1 <= n <= 20),表示了Smith管辖内的邮筒排成的点阵。

Output

只有一行,只有一个整数,表示Smith可选的不同路线的条数。

Sample Input

2 2
说明:该输入表示,Smith管辖了2*2的一个邮筒点阵。

Sample Output

2

裸插头dp

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int bi=1000000000;
int i;
struct na{
    int x,z;
    na(int xx,int zz):x(xx),z(zz){}
};
struct big{
    int a[100];
    big(){
        memset(a,0,sizeof(a));
        a[0]=1;
    }
    big operator =(int x){
        if (x==0){
            memset(a,0,sizeof(a));
            a[0]=1;
            return *this;
        }
        a[0]=0;
        while (x){
            a[0]++;
            a[a[0]]=x%bi;
            x/=bi;
        }
        if (!a[0]) a[0]=1;
        return *this;
    }
    big operator +(const big &x){
        big r;
        if (a[0]<x.a[0]) r.a[0]=x.a[0];else r.a[0]=a[0];
        for (i=1;i<=r.a[0];i++) r.a[i]=a[i]+x.a[i];
        for (i=1;i<=r.a[0];i++)
        if (r.a[i]>=bi){
            r.a[i]-=bi;r.a[i+1]++;
            if (i==r.a[0]) r.a[0]++;
        }
        return r;
    }
}ans;
int n,m,x,y,z,a[21],k,p1,p2;
bool map[21][21];
big f[2][177148];
int v[2][177148];
queue <na> q;
inline int gx(int x,int q1,int q2){k=0;for (register int i=m+1;i;i--) k=k*3+(i==x?q1:(i==x+1?q2:a[i]));return k;}
inline void up(int x,int z,big lj){
    x++;
    k=x%2;
    if (v[k][z]!=x) v[k][z]=x,f[k][z]=0,q.push(na(x,z));
    f[k][z]=f[k][z]+lj;
}
int main(){
    register int i,j;
    scanf("%d%d",&n,&m);
    if (n<m) swap(n,m);
    for (i=1;i<=m;i++)
    for (j=1;j<=n;j++)
    map[i][j]=1;
    f[0][0]=v[0][0]=1;
    q.push(na(0,0));
    while(!q.empty()){
        na no=q.front();q.pop();
        big an=f[no.x%2][no.z];
        if(no.x%m==0) no.z*=3;
        x=no.x%m+1;y=no.x/m+1;
        for (i=1;i<=m+1;i++) a[i]=0;
        for (i=1,j=no.z;j;i++,j/=3) a[i]=j%3;
        if (!map[x][y]) up(no.x,gx(x,0,0),an);else
        if (a[x]==1&&a[x+1]==2){
            if (x==m&&y==n) ans=ans+an;
        }else if (a[x]==2&&a[x+1]==1) up(no.x,gx(x,0,0),an);else
        if (a[x]==0&&a[x+1]==0){
            if (map[x][y+1]&&map[x+1][y]) up(no.x,gx(x,1,2),an);
        }else if (a[x]==0){
            if (map[x+1][y]) up(no.x,gx(x,0,a[x+1]),an);
            if (map[x][y+1]) up(no.x,gx(x,a[x+1],0),an);
        }else if (a[x+1]==0){
            if (map[x+1][y]) up(no.x,gx(x,0,a[x]),an);
            if (map[x][y+1]) up(no.x,gx(x,a[x],0),an);
        }else if (a[x]==a[x+1]){
            p1=p2=0;
            if (a[x]==1)
            for (j=0,i=x+2;i<=m;i++){
                if (a[i]==1) j--;
                if (a[i]==2) j++;
                if (j>0&&!p1) p1=i,j--;
                if (j>0&&p1){p2=i;break;}
            }else
            for (j=0,i=x-1;i;i--){
                if (a[i]==1) j++;
                if (a[i]==2) j--;
                if (j>0&&!p2) p2=i,j--;
                if (j>0&&p2){p1=i;break;}
            }
            a[p1]=1;a[p2]=2;up(no.x,gx(x,0,0),an);
        }
    }
    ans=ans+ans;
    if (ans.a[0]==1&&ans.a[1]==0) printf("1\n");else{
        printf("%d",ans.a[ans.a[0]]);
        for (i=ans.a[0]-1;i;i--) printf("%09d",ans.a[i]);
    }
}
时间: 2024-10-25 17:17:01

vijos 1110小胖邮递员;bzoj 1210: [HNOI2004]邮递员的相关文章

【BZOJ1210】[HNOI2004]邮递员 插头DP+高精度

[BZOJ1210][HNOI2004]邮递员 Description Smith在P市的邮政局工作,他每天的工作是从邮局出发,到自己所管辖的所有邮筒取信件,然后带回邮局.他所管辖的邮筒非常巧地排成了一个m*n的点阵(点阵中的间距都是相等的).左上角的邮筒恰好在邮局的门口. Smith是一个非常标新立异的人,他希望每天都能走不同的路线,但是同时,他又不希望路线的长度增加,他想知道他有多少条不同的路线可走.[任务描述]你的程序需要根据给定的输入,给出符合题意的输出:? 输入包括点阵的m和n的值:?

BZOJ 1212: [HNOI2004]L语言( dp + trie )

因为单词很短...用trie然后每次dp暴力查找...用哈希+dp应该也是可以的.... --------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<bitset> using namespace

BZOJ 1211: [HNOI2004]树的计数( 组合数学 )

知道prufer序列就能写...就是求个可重集的排列...先判掉奇怪的情况, 然后答案是(N-2)!/π(d[i]-1)! --------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; c

BZOJ 1207: [HNOI2004]打鼹鼠( dp )

dp.. dp[ i ] = max( dp[ j ] + 1 ) ---------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #define rep( i , n ) for

BZOJ 1208: [HNOI2004]宠物收养所

1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 7514  Solved: 2982[Submit][Status][Discuss] Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^

bzoj 1208: [HNOI2004]宠物收养所 set

1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 7328  Solved: 2892[Submit][Status][Discuss] Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^

【动态规划】【最长公共子序列】Vijos P1111 小胖的水果

题目链接: https://vijos.org/p/1111 题目大意: 多组数据,给两个字符串s1,s2,求把s1,s2拆开从前往后合并后最短是多少 apple + peach = appleach ananas  + banana = bananas pear + peach = pearch 题目思路: [动态规划] 先求最长公共子序列,f[i][j]表示s1匹配到第i位,s2匹配到第j位的最多重叠字母数. 最终答案=len(s1)+len(s2)-f[len(s1)][len(s2)]

BZOJ 1211: [HNOI2004]树的计数 purfer序列

1211: [HNOI2004]树的计数 Description 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,编程需要输出满足d(vi)=di的树的个数. Input 第一行是一个正整数n,表示树有n个结点.第二行有n个数,第i个数表示di,即树的第i个结点的度数.其中1<=n<=150,输入数据保证满足条件的树不超过10^17个. Output 输出满足条件的树有多少棵

BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]

1212: [HNOI2004]L语言 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1367  Solved: 598[Submit][Status][Discuss] Description 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D是若干个单词的集合. 我们称一段文章T在某个字典D下是可以被理解的,是指如果文