【caioj】1489: 基于连通性状态压缩的 动态规划问题:Formula 1 Ural1519

来源:互联网 发布:做淘宝后感想 编辑:程序博客网 时间:2024/05/22 01:41

今天在TYB大佬的带领下学了一发新姿势啊!!
感觉几年前的省选考过插头DP,就有一点点想学了。。
但是好像以前研究过一小阵子。。
由于没看懂就放弃了。。
然后这次跟着TYB大佬又来了一发。。
感觉还好
感觉这个算法的核心思想就是不断地分类讨论。。
要注意的地方很多。。
然后想学的人还是先看看论文,弄清楚点概念什么的
至于分类讨论,看代码就好
下面是我的代码,有“详细”的注释
哦,还有,学这个东西的时候一定要有纸和笔。。没看懂的地方一定要画。。不要相信什么人脑是无敌的

#include<cstdio>#include<cstring>#define ADD add(st,sum)typedef long long LL;const int MOD=100037;const int N=15;bool map[N][N];//是不是可以走 int n,m;int xx=-1,yy;//我们要寻找一个最下   最右的点——>当到他的时候就可以累计答案了LL ans=0;//答案个数LL a[2][MOD];//这种状态的数目,其实差不多是来辅助下面的数组 int b[2][MOD];//状态int num[2];//状态个数int HASH[MOD];/*0:无插头状态1:左括号插头2:右括号插头*/int get (int x,int p)//第j位   当然是四进制里面的第j位啦 {return (x>>(p-1)*2)&3;}int now=0;void add (int st,LL sum)//给当前的决策状态加上这个状态{    int ss=st%MOD;    while (HASH[ss]!=-1&&b[now][HASH[ss]]!=st)    {        ss++;ss%=MOD;        if (ss==0) ss=1;    }    if (HASH[ss]==-1)    {        HASH[ss]=++num[now];        b[now][num[now]]=st;        a[now][num[now]]=sum;    }    else a[now][HASH[ss]]+=sum;}void change (int &s,int p,int v)//把s的第p位改为v{    s=s^(get(s,p)<<(p-1)*2);    s=s^(v<<(p-1)*2);}void solve (){    a[0][1]=1;num[0]=1;b[0][1]=0;    for (int u=1;u<=n;u++)    {        for (int i=1;i<=m;i++)//当前的转移节点,我们要尝试吧这个节点转到下一个        {            now^=1;            num[now]=0;            memset(HASH,-1,sizeof(HASH));            for (int k=1;k<=num[now^1];k++)//继承上一个轮廓线的状态            {                int st=b[now^1][k];                 LL sum=a[now^1][k];                int p=get(st,i);//获得“竖着的”那个插头状态                 int q=get(st,i+1);//获得“横着的”那个插头状态             //  printf("%d %d %d %d %d %d\n",u,i,k,st,p,q);                if (map[u][i]==false)//这个是障碍点                {                    if (p+q==0) ADD;//要是可以把它绕开就好了                     continue;                }                if (p+q==0)//没有连到当前格子                {                    if (map[u][i+1]&&map[u+1][i])                    {                        change(st,i,1);                        change(st,i+1,2);                        ADD;                    }                }                else if (p==0&&q!=0)                {                    if (map[u][i+1]==true) ADD;                    if (map[u+1][i]==true)                    {                        change(st,i,q);                        change(st,i+1,0);                        ADD;                    }                }                else if (p!=0&&q==0)                {                    if (map[u+1][i]==true) ADD;                    if (map[u][i+1]==true)                    {                        change(st,i,0);                        change(st,i+1,p);                        ADD;                    }                }                else if (p==1&&q==2)                {                    if (u==xx&&i==yy)                        ans+=sum;                }                else if (p==2&&q==1)                {                    change(st,i,0);                    change(st,i+1,0);                    ADD;                }                else if (p==1&&q==1)                {                    int top=1;                    for (int pos=i+2;pos<=m+1;pos++)                    {                        int temp=get(st,pos);                        if (temp==1) top++;                        if (temp==2) top--;                        if (top==0)                        {                            change(st,i,0);                            change(st,i+1,0);                            change(st,pos,1);                            ADD;                            break;                        }                    }                }                else if (p==2&&q==2)                {                    int top=1;                    for (int pos=i-1;pos>0;pos--)                    {                        int temp=get(st,pos);                        if (temp==2) top++;                        if (temp==1) top--;                        if (top==0)                        {                            change(st,i,0);                            change(st,i+1,0);                            change(st,pos,2);                            ADD;                            break;                        }                    }                }            }        }        for (int i=1;i<=num[now];i++) b[now][i]<<=2;    }}int main(){    memset(map,false,sizeof(map));    scanf("%d%d",&n,&m);    for (int u=1;u<=n;u++)    {        char ss[15];        scanf("%s",ss+1);        for (int i=1;i<=m;i++)            if (ss[i]=='.')                 {xx=u;yy=i;map[u][i]=true;}    }    if (xx==-1) {printf("0");return 0;}    solve();    printf("%lld\n",ans);    return 0;}
阅读全文
0 0
原创粉丝点击