• #2099. 「CQOI2015」标识设计(插头dp)


    题目描述


    题解

    第一次写插头dp

    求哈密顿回路:https://blog.csdn.net/litble/article/details/79369147,本质是维护轮廓线+左右括号序列

    本题只需要维护下/右插头即可,状态数是C(m,3)级别的,压一压即可

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define ll long long
    //#define file
    using namespace std;
    
    ll f[4527][4][2],g[4527][4][2],ans;
    int num[31][31][31],b[4527][3],n,m,i,j,k,l,tot,I[3];
    bool bz[31][31];
    char ch;
    
    void swap(int &x,int &y) {int z=x;x=y;y=z;}
    
    int main()
    {
    	#ifdef file
    	freopen("loj2099.in","r",stdin);
    	#endif
    	
    	scanf("%d%d",&n,&m);
    	fo(i,1,n)
    	{
    		fo(j,1,m)
    		{
    			ch=getchar();
    			while (ch!='.' && ch!='#') ch=getchar();
    			bz[i][j]=ch=='#';
    		}
    	}
    	
    	tot=1;num[0][0][0]=1;b[1][0]=0,b[1][1]=0,b[1][2]=0;
    	fo(i,1,m)
    	{
    		num[i][0][0]=++tot;
    		b[tot][0]=i,b[tot][1]=0,b[tot][2]=0;
    		fo(j,1,i-1)
    		{
    			num[i][j][0]=++tot;
    			b[tot][0]=i,b[tot][1]=j,b[tot][2]=0;
    			fo(k,1,j-1)
    			num[i][j][k]=++tot,b[tot][0]=i,b[tot][1]=j,b[tot][2]=k;
    		}
    	}
    	
    	f[1][0][0]=1;
    	fo(i,1,n)
    	{
    		fo(j,0,m-1)
    		{
    			memset(g,0,sizeof(g));
    			fo(k,1,tot)
    			{
    				fo(l,0,3)
    				{
    					if (!bz[i][j+1])
    					{
    						I[0]=b[k][0],I[1]=b[k][1],I[2]=b[k][2];
    						if (I[0]==j+1) g[num[I[1]][I[2]][0]][l][1]+=f[k][l][0];
    						else
    						if (I[1]==j+1) g[num[I[0]][I[2]][0]][l][1]+=f[k][l][0];
    						else
    						if (I[2]==j+1) g[num[I[0]][I[1]][0]][l][1]+=f[k][l][0];
    						else
    						if (l<3)
    						{
    							I[2]=j+1;
    							if (I[2]>I[1]) swap(I[1],I[2]);
    							if (I[1]>I[0]) swap(I[0],I[1]);
    							g[num[I[0]][I[1]][I[2]]][l+1][0]+=f[k][l][0];
    						}
    						
    						if (b[k][0]!=j+1 && b[k][1]!=j+1 && b[k][2]!=j+1)
    						{
    							g[k][l][0]+=f[k][l][1];
    							g[k][l][1]+=f[k][l][1];
    						}
    					}
    					if (!bz[i][j+1] || (b[k][0]!=j+1 && b[k][1]!=j+1 && b[k][2]!=j+1)) g[k][l][0]+=f[k][l][0];
    				}
    			}
    			memcpy(f,g,sizeof(f));
    		}
    		
    		if (i<n)
    		{
    			fo(k,1,tot)
    			{
    				fo(l,0,3)
    				f[k][l][1]=0;
    			}
    		}
    	}
    	printf("%lld
    ",f[1][3][0]);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    博客样式备份
    2018年终总结
    技术博客的太监
    LeetCode 日常填坑
    互联网之父
    TotoiseSVN的使用方法
    常用CMD命令
    量化策略
    浏览器加载js的阻塞与非阻塞
    Vue核心之数据劫持
  • 原文地址:https://www.cnblogs.com/gmh77/p/13499213.html
Copyright © 2020-2023  润新知