题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4026

Unlock the Cell Phone

Time Limit: 6000/3000 MS (Java/Others)
Memory Limit: 65768/65768 K (Java/Others)
#### 问题描述
> Modern high-tech cell phones use unlock patterns to unlock the system. The pattern is usually a 3*3 dot array. By moving your finger over there dots, you can generate your personal unlock pattern. More specifically, press your finger over any starting dot, then slide all the way to the next dot, touch it, and so on. Jumping is not allowed. For example, starting from dot 1, you can slide to touch dot 2, dot 4 and dot 5, but sliding directly to dot 3, dot 7 or dot 9 are not allowed. Note that sliding from 1 to 6 and 8 is also allowed because they are not considered as jumping over any dot. However, you can jump a dot if it has been touched before. For example, staring with 1-5-9-6, you can slide directly to dot 4.
> Here is a very particular cell phone. It has a dot array of size n*m. Some of the dots are ordinary ones: you can touch, and slide over them when touched before; some are forbidden ones: you cannot touch or slide over them; some are inactive ones: you cannot touch them, but can slide over them. Each dot can only be touched once. You are required to calculate how many different unlock patterns passing through all the ordinary dots.

输入

The input contains several test cases. Each test case begins with a line containing two integers n and m (1 <= n, m <= 5), indicating the row and column number of the lock keypad. The following n lines each contains m integers kij indicating the properties of each key, kij=0 stands for an ordinary key, kih=1 stands for a forbidden key; and kij=2 stands for an inactive key. The number of ordinary keys is greater than zero and no more than 16.

输出

For each test, output an integer indicating the number of different lock patterns.

样例输入

2 2

0 0

0 0

3 3

0 0 0

0 2 1

0 0 0

样例输出

24

2140

题意

给你一个手势解锁的n*m的键盘,0表示可以正常使用的,1表示不能碰触并且不能越过的,2表示不能碰触但是可以越过的。 问要把所有正常的都激活一遍的总的方案数有多少种。

题解

处理下什么情况是非法的,然后把可激活的单独拿出来激活下。

代码

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=10000000000000000LL;
const double eps=1e-9; const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxm=17; int arr[11][11];
int mp[33][33];
int mmp[33];
int n,m; VI G[33][33];
LL dp[1<<maxm][maxm]; ///判断中间有没有经过还没访问过的点或者中间有没有静止越过的点
bool ok(int sta,int s1,int s2){
if(mp[s1][s2]==1) return false;
rep(i,0,G[s1][s2].sz()){
int x=G[s1][s2][i];
int id=mmp[x];
if(!(sta&(1<<id))) return false;
}
return true;
} void init(){
clr(mp,0);
clr(mmp,-1);
rep(i,0,33) rep(j,0,33) G[i][j].clear();
} int main() {
while(scf("%d%d",&n,&m)==2&&n){
init(); ///把等于0的点单独挖出来状压
VI vec;
rep(i,0,n) rep(j,0,m){
scf("%d",&arr[i][j]);
if(arr[i][j]==0){
vec.pb(i*m+j);
}
} rep(i,0,vec.sz()){
mmp[vec[i]]=i;
} ///处理线段中间的点
rep(i,0,vec.sz()){
rep(j,0,vec.sz()){
if(i==j) continue;
int xi=vec[i]/m,yi=vec[i]%m;
int xj=vec[j]/m,yj=vec[j]%m; for(int x=min(xi,xj);x<=max(xi,xj);x++){
for(int y=min(yi,yj);y<=max(yi,yj);y++){
if(x==xi&&y==yi||x==xj&&y==yj) continue;
if((yi-y)*(xj-x)!=(yj-y)*(xi-x)) continue; if(arr[x][y]==1){
mp[vec[i]][vec[j]]=1;
}
if(mp[vec[i]][vec[j]]==1) continue; if(arr[x][y]==0){
G[vec[i]][vec[j]].pb(x*m+y);
}
}
}
}
} ///状压
int tot=vec.sz(); clr(dp,0);
rep(i,0,tot){
dp[1<<i][i]=1;
} rep(i,0,(1<<tot)){
rep(j,0,tot){
if(!(i&(1<<j))) continue;
rep(k,0,tot){
if(k==j||(i&(1<<k))==0) continue; if(ok(i,vec[k],vec[j])){
dp[i][j]+=dp[i^(1<<j)][k];
}
}
}
} LL ans=0;
rep(i,0,tot){
ans+=dp[(1<<tot)-1][i];
} prf("%lld\n",ans); }
return 0;
} //end-----------------------------------------------------------------------

HDU 4026 Unlock the Cell Phone 状压dp(类似TSP)的更多相关文章

  1. HDU 5067 Harry And Dig Machine(状压DP)(TSP问题)

    题目地址:pid=5067">HDU 5067 经典的TSP旅行商问题模型. 状压DP. 先分别预处理出来每两个石子堆的距离.然后将题目转化成10个城市每一个城市至少经过一次的最短时间 ...

  2. HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]

    题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...

  3. HDU 1074:Doing Homework(状压DP)

    http://acm.hdu.edu.cn/showproblem.php?pid=1074 Doing Homework Problem Description Ignatius has just ...

  4. hdu 2167 方格取数 【状压dp】(经典)

    <题目链接> 题目大意: 给出一些数字组成的n*n阶矩阵,这些数字都在[10,99]内,并且这个矩阵的  3<=n<=15,从这个矩阵中随机取出一些数字,在取完某个数字后,该数 ...

  5. HDU 6149 Valley Numer II(状压DP)

    题目链接 HDU6149 百度之星复赛的题目……比赛的时候并没有做出来. 由于低点只有15个,所以我们可以考虑状压DP. 利用01背包的思想,依次考虑每个低点,然后枚举每个状态. 在每个状态里面任意枚 ...

  6. HDU 4917 Permutation(拓扑排序 + 状压DP + 组合数)

    题目链接 Permutation 题目大意:给出n,和m个关系,每个关系为ai必须排在bi的前面,求符合要求的n的全排列的个数. 数据规模为n <= 40,m <= 20. 直接状压DP空 ...

  7. HDU 2809 God of War (状压DP)

    God of War Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  8. 状压DP 从TSP问题开始入门哦

      一开始学状压DP难以理解,后来从TSP开始,终于入门了nice!!!! 旅行商问题 :    给定n个城市和两两相互的距离 ,求一条路径经过所有城市,并且路径达到最下仅限于; 朴树想法: 做n个城 ...

  9. HDU 3681 Prison Break 越狱(状压DP,变形)

    题意: 给一个n*m的矩阵,每个格子中有一个大写字母,一个机器人从‘F’出发,拾取所有的开关‘Y’时便能够越狱,但是每走一格需要花费1点能量,部分格子为充电站‘G’,每个电站只能充1次电.而且部分格子 ...

随机推荐

  1. Linux下onvif客户端关于ipc摄像头的搜索

    设备搜索:要访问一个IPC摄像头,或者说要调用IPC摄像头提供的WEB服务接口,就要先知道其IP地址,这就是设备发现的过程,或者叫设备搜索的过程.IPC摄像头用的是239.255.255.250(端口 ...

  2. 【Verilog HDL】赋值语句之阻塞赋值方式与非阻塞赋值方式

    刚开始接触Verilog HDL语言时,这种硬件描述语言有一点与软件的程序设计语言直观上的最大区别大概就是这个赋值语句了(这里只是强调直观上的最大区别,事实上的最大区别并非如此). Verilog H ...

  3. 第六周课上测试-1-ch02

    第六周课上测试-1-ch02 1. 要求: 1.参考附图代码,编写一个程序 "week0601学号.c",判断一下你的电脑是大端还是小端. 2. 提交运行结果"学号XXX ...

  4. JavaWeb总结(六)

    获取原始表单数据 - POST请求不仅可以传输文本信息还可以传输二进制数据 - 如果想得到请求中参数的原始字节数据,可以使用HttpServletRequest对象提供的getInputSteam() ...

  5. 游戏手柄(JoyStick)编程学习笔记(2)

    在我的上一篇博客中(http://blog.csdn.net/liyuanbhu/article/details/51714045),介绍了通过 multimedia joystick API 来访问 ...

  6. 01-网格走法 Python

    1.题目描述 有一个X*Y的网格,小团要在此网格上从左上角到右下角,只能走格点且只能向右或向下走.请设计一个算法,计算小团有多少种走法.给定两个正整数int x,int y,请返回小团的走法数目. 输 ...

  7. asp.net core 自定义中间件和service

    首先新建项目看下main方法: public static void Main(string[] args) { var host = new WebHostBuilder() .UseKestrel ...

  8. Magic Trackpad 2 on win10 x64

    可以使用操作: 触击 触击拖拽 双击 支手滚动:上下,左右 右键配置:左下角,右下角点击实现 可以试用28天,收费 $9.5 官方地址:http://www.trackpadmagic.com/mag ...

  9. Float浮点数的使用和条件

    在这里简单的说一下,我对浮点数的理解,可能说的比较浅,老师也没有说,只是略微的提了一下,完全是我自己个人的理解. 我觉得float浮点数的用法和int的用法有些雷同,浮点数用于计算小数点单位,我们先可 ...

  10. vue mock(模拟后台数据) +axios 简单实例(二)

    需装上axios,build文件夹中webpack.dev.conf.js文件添加上vue mock配置的东东,  如,继(一) //组件<template> <div> &l ...