hdu4064 三进制状态压缩 好题!

还不太会做这类题,总之感觉有点难啊。

用深搜代替打表求出一行所有的可行状态,注意要进行剪枝

这是自己理解的代码,但是tle了

#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define maxn 600005
int n,m,dp[2][maxn],sum;
char mp[15][15][15];
int a[200],tag,flag,s[15];
//
void dfs(int r,int num,int up,int down,int right){//用dfs搜索出第r行的下状态,上状态 和右侧颜色
    int xx,rr,yy,ll,i;
    if(num==m){//搜满了一行
        if(r==0)dp[flag][down]+=tag;//如果是第一行,那么只要把组成这种状态的方案数加上即可
        else {
            dp[flag][down]+=dp[(flag+1)%2][up]*tag;//加上上一行下状态为up的计数值
            dp[flag][down]%=mod;
        }
        return;
    }
    for(int i=1;i<4;i++)//判断改行第i个方块是不是四方相同的
        if(mp[r][num][i]!=mp[r][num][0])break;
    if(i==4){//四方相同的块直接跳过即可,并且这一行的结果要加上4
        tag*=4;
        xx=a[mp[r][num][0]];
        if(xx==right || right==-1)dfs(r,num+1,up*3+xx,down*3+xx,xx);
        tag/=4;
        return;
    }

    for(int i=0;i<4;i++){//枚举该方块的安放方式,符合条件的进入下一轮深搜
        xx=a[mp[r][num][i]];//下一格上方
        rr=a[mp[r][num][(i+1)%4]];//下一格右侧
        yy=a[mp[r][num][(i+2)%4]];//下一格下放
        ll=a[mp[r][num][(i+3)%4]];//下一格左侧
        if(right==-1 || ll==right)//如果是第一格或者左侧对上这一格的右侧,就可以往下搜了
            dfs(r,num+1,up*3+xx,down*3+yy,rr);
    }
}

int ncase,t;
void init(){
    cin>>ncase;a[‘F‘]=0,a[‘C‘]=1,a[‘R‘]=2;
    s[0]=1;
    for(int i=1;i<=12;i++)s[i]=s[i-1]*3;//使用三进制
    flag=0;
    memset(dp,0,sizeof dp);
}

int main(){
    init();
    for(int t=1;t<=ncase;t++){
        cin>>n>>m;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                cin>>mp[i][j];

        for(int i=0;i<n;i++){//利用滚动数组,dp[flag][s]表示第i行状态s下的方案数
            tag=1;flag^=1;
            memset(dp[flag],0,sizeof dp[flag]);
            dfs(i,0,0,0,-1);
        }

        sum=0;
        for(int i=0;i<s[m];i++)//求和
            sum+=dp[flag][i],sum%=mod;

        printf("Case %d: %lld\n",t,sum);
    }
}

原文地址:https://www.cnblogs.com/zsben991126/p/10364515.html

时间: 2024-10-08 14:13:16

hdu4064 三进制状态压缩 好题!的相关文章

HDU 3001 Travelling (三进制状态压缩 DP)

题意:有 n 个city,可以选择任一城市作为起点,每个城市不能访问超过2次, 城市之间有权值,问访问全部n个城市需要的最小权值. 思路:因为每个城市可以访问最多两次,所以用三进制表示访问的状态. 详细见代码注释!!!! #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #include<cmath> #inclu

hdu-3001 三进制状态压缩+dp

用dp来求最短路,虽然效率低,但是状态的概念方便解决最短路问题中的很多限制,也便于压缩以保存更多信息. 本题要求访问全图,且每个节点不能访问两次以上.所以用一个三进制数保存全图的访问状态(3^10,空间是足够的),用dp[z+bit[j]][j]=dp[z][i]+ct[i][j]就可以表示,从上一状态以i为结束点,转移到把j加入路径末端后的状态(感叹一下位运算的神奇). // // main.cpp // hdu_3001 // // Created by Luke on 2016/11/12

hdu3001 (三进制状态压缩 dp)

src: http://acm.hdu.edu.cn/showproblem.php?pid=3001 思路:每个顶点经过最多2次,也就是有0 1 2三种状态!用bit[]存三进制下各位的值(这样dp的状态概念就可以解决最短路问题的许多限制,通过压缩可以保存更多的值~),dp[z][j]表示z状态下,以j为终点的路径费用!!! 待更~~~ 原文地址:https://www.cnblogs.com/WindFreedom/p/8763093.html

《转》二进制与三进制的那些趣题

http://blog.csdn.net/zhuxiaoyang2000/article/details/6091767 先来思考几个问题,并不难,各位大牛应能秒杀: 1. 小明是个卖苹果的,小红一次在小明那买N(N<1024)个苹果.小明每次都要数N个苹果给小红,唉,太麻烦了.于是小明想出了一种方法:他把苹果分在10个袋子中,则无论小红来买多少个苹果,则他都可以整袋整袋的拿给小红.问怎样分配苹果到各个袋子? 2. 有16种溶液,其中有且只有一种是有毒的,这种有毒的溶液与另一种试剂A混合会变色,

POJ-3254-Corn Fields-DP+状态压缩(入门题)

题目链接:http://poj.org/problem?id=3254 题目意思:给你一个n*m的牧场,叫你带牛去吃草,其中0代表没有草不可以放牧,1代表有草可以放牧.而且两头牛不可以相邻,叫你求所有可能的放牧方案. 思路:这是个状态压缩的基础题,刚学状态压缩的可以用这个题目来理解状态压缩:(如果是刚学DP我建议理解题意后先粗略的看一下代码后再边看代码边看我的思路,效果更佳) 1.题目告诉我们两头牛不能相邻,那么我们就可以枚举出每一行的所有情况,并且用数组st保存起来:怎么枚举每一种情况呢,题目

poj1185 状态压缩经典题

状态压缩的好题,直接求会爆内存,先把所有可能的状态求出来存在stk里,然后f[i][k][t]表示i行状态为t,i-1状态为k,由i-1状态来推出i状态即可 注意要打好边际条件的状态,并且某个可行状态必须由前一个可行状态推出 /* f[i][k][t]表示第i行状态为t,第i-1行状态为k的炮兵数 边际条件:第一行为任意可行状态即dp[1][1][i]=num[i] */ #include<bits/stdc++.h> using namespace std; #define ll long

dp之状态压缩水题总结

状态压缩dp 其实就是 将状态表示成二进制,然后用位运算进行求解 poj 3311 Hie with the Pie Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5080   Accepted: 2706 Description The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unf

状态压缩简单题

状态压缩·一 题目传送:#1044 : 状态压缩·一 AC代码: #include <map> #include <set> #include <list> #include <cmath> #include <deque> #include <queue> #include <stack> #include <bitset> #include <cctype> #include <cstdi

Traveling by Stagecoach 状态压缩裸题

Traveling by Stagecoach dp[s][v]  从源点到达  v,状态为s,v的最小值.  for循环枚举就行了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector>