POJ-1739:Tony's Tour
来源:互联网 发布:淘宝买家怎么提升等级 编辑:程序博客网 时间:2024/06/08 16:31
Tony's Tour
Time Limit: 1000MS Memory Limit: 30000KTotal Submissions: 4217 Accepted: 1967
Description
A square township has been divided up into n*m(n rows and m columns) square plots (1<=N,M<=8),some of them are blocked, others are unblocked. The Farm is located in the lower left plot and the Market is located in the lower right plot. Tony takes her tour of the township going from Farm to Market by walking through every unblocked plot exactly once.
Write a program that will count how many unique tours Betsy can take in going from Farm to Market.
Write a program that will count how many unique tours Betsy can take in going from Farm to Market.
Input
The input contains several test cases. The first line of each test case contain two integer numbers n,m, denoting the number of rows and columns of the farm. The following n lines each contains m characters, describe the farm. A '#' means a blocked square, a '.' means a unblocked square.
The last test case is followed by two zeros.
The last test case is followed by two zeros.
Output
For each test case output the answer on a single line.
Sample Input
2 2....2 3#.....3 4............0 0
Sample Output
114
思路:插头DP。这算是真正的入门题了吧。真的没想到DP里面也有这么长的代码。。。
这是第一次写这样的插头DP,状态转移有点复杂。主要参考了http://blog.csdn.net/xingyeyongheng/article/details/24415517
不过还没了解什么是插头DP的话,建议先仔细认真的看陈丹琦的《基于连通性状态压缩的动态规划问题》https://wenku.baidu.com/view/a6dce6c76137ee06eff918d1.html
#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>using namespace std;const int MAX=1000+10; //开大了会TLEint head[MAX],nex[MAX],hash[MAX],size; //hash链表long long d[2][MAX]; //二维滚动数组long long tp[2][MAX]; //记录状态long long total[2]; //状态总数量int ex,ey; //记录最后一个非'#'的格子int n,m;int now,pre;char s[15][15];void insert(int x,long long sum) //插入x这个状态{ int pos=x%MAX; for(int i=head[pos];i!=-1;i=nex[i]) { if(x==tp[now][hash[i]]) //找到相同的状态 { d[now][hash[i]]+=sum; return; } } total[now]++; //没找到相同状态就插入这个状态 tp[now][total[now]]=x; d[now][total[now]]=sum; hash[size]=total[now]; nex[size]=head[pos]; head[pos]=size++;}int main(){ while(cin>>n>>m&&(n||m)) { for(int i=0;i<n;i++)scanf("%s",s[i]); s[n][0]=s[n][m-1]='.'; for(int j=1;j<m-1;j++)s[n][j]='#'; n++; //这里额外的加了2行以形成回路 for(int j=0;j<m;j++)s[n][j]='.'; // .*****. n++; // ....... for(int i=0;i<n;i++) { for(int j=0;j<m;j++)if(s[i][j]=='.')ex=i,ey=j; } memset(d,0,sizeof d); memset(head,-1,sizeof head); memset(total,0,sizeof total); size=0; pre=0,now=1; d[0][1]=1; tp[0][1]=0; total[0]=1; long long ans=0; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { for(int k=1;k<=total[pre];k++) { int state=tp[pre][k]; //取出状态 int left=state&3; //左插头状况(0表示没有插头,1表示右括号插头,2表示左括号插头) int up=state&((1<<(2*m+1))+(1<<(2*m))); //上插头状况(0表示没有插头,1<<(2*m)表示右括号插头,1<<(2*m+1)表示左括号插头) if(s[i][j]=='#') //当前位置不能通过 { if(left==0&&up==0)insert(state<<2,d[pre][k]); continue; } if(left==0&&up==0)//左边上边都没插头 { if(i+1>=n||j+1>=m||s[i+1][j]=='#'||s[i][j+1]=='#')continue; insert((state<<2)^9,d[pre][k]); //新加入一个连通分量 } if(left==0&&up) //左边没有插头,上边有 { if(j+1<m&&s[i][j+1]=='.') //向右延伸插头 { if(up&(1<<(2*m)))insert((state<<2)^(up<<2)^1,d[pre][k]); //up为右括号 if(up&(1<<(2*m+1)))insert((state<<2)^(up<<2)^2,d[pre][k]); //up为左括号 } if(i+1<n&&s[i+1][j]=='.') //向下延伸插头 { if(up&(1<<(2*m)))insert((state<<2)^(up<<2)^4,d[pre][k]); //up为右括号 if(up&(1<<(2*m+1)))insert((state<<2)^(up<<2)^8,d[pre][k]); //up为左括号 } } if(left&&up==0) //上边没有插头,左边有 { if(j+1<m&&s[i][j+1]=='.') //向右延伸插头 { if(left&1)insert((state<<2)^(left<<2)^1,d[pre][k]); //left为右括号 if(left&2)insert((state<<2)^(left<<2)^2,d[pre][k]); //left为左括号 } if(i+1<n&&s[i+1][j]=='.') //向下延伸插头 { if(left&1)insert((state<<2)^(left<<2)^4,d[pre][k]); //lfet为右括号 if(left&2)insert((state<<2)^(left<<2)^8,d[pre][k]); //left为左括号 } } if(left&&up) //左方上方都有插头 { if(left==1&&(up&(1<<(2*m+1)))) //left为右括号,up为左括号 { insert((state<<2)^(left<<2)^(up<<2),d[pre][k]); } if(left==1&&(up&(1<<(2*m)))) //left为右括号,up为右括号 { for(int sum=1,t=j-1,l=2;t>=0;l+=2,t--)//往左找最近的一个左括号 { if((2<<l)&state)sum--; if((1<<l)&state)sum++; if(sum==0) //找到了,将其改为右括号 { insert((state<<2)^(left<<2)^(up<<2)^(3<<(l+2)),d[pre][k]); break; } } } if(left==2&&(up&(1<<(2*m)))) //left为左括号,up为右括号 { if(i==ex&&j==ey) //只有最后一个格子才能合并形成回路 { ans=d[pre][k]; } } if(left==2&&(up&(1<<(2*m+1)))) //left为左括号,up为左括号 { for(int sum=1,t=j+1,l=2;t<m;l+=2,t++)//往右找最近的一个右括号 { if(( (1<<(2*m+1)) >>l)&state)sum++; if(( (1<<(2*m)) >>l)&state)sum--; if(sum==0) //找到了,将其改为左括号 { insert((state<<2)^(left<<2)^(up<<2)^(((1<<(2*m+1))+(1<<(2*m)))>>(l-2)),d[pre][k]); break; } } } } } memset(d[pre],0,sizeof d[pre]); total[pre]=0; now^=1; pre^=1; memset(head,-1,sizeof head); size=0; } } cout<<ans<<endl; } return 0;}
阅读全文
1 0
- poj 1739 Tony's Tour
- poj 1739 Tony's Tour
- POJ 1739 Tony's Tour
- POJ 1739 Tony's Tour
- 【POJ 1739】Tony's Tour
- POJ 1739 Tony's Tour
- POJ-1739:Tony's Tour
- poj 1739 Tony's Tour 插头dp
- poj 1739 Tony's Tour 插头dp
- POJ 1739 Tony's Tour (插头DP)
- poj 1739 Tony's Tour(插头dp)
- POJ 1739 Tony's Tour 插头DP
- poj 1739 Tony's Tour 插头dp
- POJ 1739 Tony's Tour 笔记
- POJ 1739 Tony's Tour 解题报告(插头DP)
- POJ - 1739 Tony's Tour (单回路插头dp)
- poj 1739 Tony's Tour 插头dp模板题
- Tony's Tour poj1739
- 【错误解决】Intellj(IDEA) warning no artifacts configured
- Two strings hdu6170 dp递推
- [自用门户]div居中显示,加在style里面
- Servlet学习
- 高通平台常用缩写
- POJ-1739:Tony's Tour
- 删除目录及子目录下指定的文件
- AJAX_idea
- MongoDb账号验证
- Java Enum枚举替代方案--Android IntDef/StringDef Annotation注解
- Shell编程学习笔记
- Leetcode657. Judge Route Circle
- Fragment跳转相册并将选中的图片显示在Fragment的ImageView
- 机器学习---Logistic回归数学推导以及python实现