HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)...

插头DP基础题的样子。。。输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物。输出哈密顿回路(可以多回路)方案数。。。

 

看了个ppt,画了下图。。。感觉还是挺有效的。。。

参考http://www.cnblogs.com/kuangbin/archive/2012/10/02/2710343.html

以及推荐cd琦的论文ppthttp://wenku.baidu.com/view/4fe4ac659b6648d7c1c74633.html

向中学生学习~~

感觉以后可能还会要看这篇日志。所以特意加了较多的注释。。。观客可以看注释=。=推荐画示意图。。。。

复杂度O(n*m*2^(m+1))

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <string>
 7 #include <vector>
 8 #include <queue>
 9 #include <set>
10 using namespace std;
11 
12 #define ll long long
13 #define inf 0x3f3f3f3f
14 #define eps 1e-8
15 
16 int a[12][12];
17 ll dp[12][12][1<<12];
18 int main(){
19     int t,ca=0;
20     scanf("%d",&t);
21     while(t--){
22         int n,m;
23         scanf("%d%d",&n,&m);
24         for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)scanf("%d",&a[i][j]);
25         memset(dp,0,sizeof(dp));
26         dp[1][0][0]=1;
27         int ma=(1<<(m+1));
28         for(int i=1;i<=n;++i){
29             for(int j=1;j<=m;++j){
30                 for(int k=0;k<ma;++k){
31                     int d=1<<(j-1),r=1<<j;
32                     if(a[i][j]){// 该位置无障碍
33                         if( ( (k&d)&&(k&r) ) || ( (~k&d)&&(~k&r)) )// 右插下插同时有或同时无,必须翻转
34                             dp[i][j][k]=dp[i][j-1][k^d^r];
35                         else // 右插下插只有一个,可翻转可不翻转
36                             dp[i][j][k]=dp[i][j-1][k]+dp[i][j-1][k^d^r];
37                     }
38                     else {// 该位置有障碍
39                         if((k&d)==0&&(k&r)==0)// 没有右插没有下插,则方案数跟随
40                             dp[i][j][k]=dp[i][j-1][k];
41                     }
42                 }
43             }
44             if(i+1<=11)
45             for(int k=0;k<(1<<m);++k)// 换行去掉上一行的右插,下一行的开头没有进来的左插,请画图
46                 dp[i+1][0][k<<1]=dp[i][m][k];
47         }
48         printf("Case %d: There are %I64d ways to eat the trees.\n",++ca,dp[n][m][0]);
49     }
50     return 0;
51 }
View Code

 

做了上面那个入门级别的插头DP。。。做了个还是入门级别的。。。。

输入N,M<=12,以及N*M的01矩阵,'*'('.')表示有(无)障碍物。输出哈密顿单回路方案数。。。

 

这一题需要用到括号匹配,最小表示法(上面那题可以不用,我的代码就是没有用到的)。。。

这一题参考了别人的代码,尝试了2种表示方法,一种是直接存括号对应的连通分量标号,一种是只存括号的类型。。。

我的第一种方法300+ms,第二种100+ms。。。感觉还是有点区别的。。。因为存连通分量标号需要用到3位(连通分量标号最大值为MAXM/2),而括号类型只需要2位

。。

 

而这题跟上一题的区别,就是,单哈密顿回路的括号匹配,如果左插是'(',下插是')',那只能在最后一个非障碍物的位置连接。。。。

具体看代码吧。。。还是建议画下示意图。。。

 

还有一点就是,由于用到HASH,所以HASH太大太小都可能会TLE

300+ms的版本(其实就是那个链接里的。。。。):

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <string>
  7 #include <vector>
  8 #include <queue>
  9 #include <set>
 10 using namespace std;
 11 
 12 #define ll long long
 13 #define inf 0x3f3f3f3f
 14 #define eps 1e-8
 15 
 16 #define maxd 15
 17 #define HASH 100007
 18 #define STATE 1000010
 19 
 20 int n,m;
 21 int maze[maxd][maxd],code[maxd];
 22 int ch[maxd];//最小表示法使用
 23 int ex,ey;//最后一个非障碍格子的坐标
 24 struct HASHMAP{
 25     int head[HASH],nxt[STATE],sz;
 26     ll state[STATE];
 27     ll f[STATE];
 28     void clear(){sz=0;memset(head,-1,sizeof(head));}
 29     void push(ll st,ll ans){
 30         int h=st%HASH;
 31         for(int i=head[h];i!=-1;i=nxt[i])
 32             if(state[i]==st){
 33                 f[i]+=ans;
 34                 return;
 35             }
 36         state[sz]=st;
 37         f[sz]=ans;
 38         nxt[sz]=head[h];
 39         head[h]=sz++;
 40     }
 41 }hm[2];
 42 void decode(int *code,int m,ll    st){
 43     for(int i=m;i>=0;i--)code[i]=st&7,st>>=3;
 44 }
 45 ll encode(int *code,int m){//最小表示法
 46     int cnt=1;
 47     memset(ch,-1,sizeof(ch));
 48     ch[0]=0;
 49     ll st=0;
 50     for(int i=0;i<=m;i++){
 51         if(ch[code[i]]==-1)ch[code[i]]=cnt++;
 52         code[i]=ch[code[i]];
 53         st<<=3;
 54         st|=code[i];
 55     }
 56     return st;
 57 }
 58 void shift(int *code,int m){
 59     for(int i=m;i>0;i--)code[i]=code[i-1];
 60     code[0]=0;
 61 }
 62 void dpblank(int i,int j,int cur){
 63     for(int k=0;k<hm[cur].sz;k++){
 64         decode(code,m,hm[cur].state[k]);
 65         int left=code[j-1],up=code[j];
 66         if(left&&up){
 67             if(left==up){//只能出现在最后一个非障碍格子
 68                 if(i==ex&&j==ey){
 69                     code[j-1]=code[j]=0;
 70                     if(j==m)shift(code,m);
 71                     hm[cur^1].push(encode(code,m),hm[cur].f[k]);
 72                 }
 73             }
 74             else{//不在同一个连通分量则合并
 75                 code[j-1]=code[j]=0;
 76                 for(int t=0;t<=m;t++)
 77                     if(code[t]==up)code[t]=left;
 78                 if(j==m)shift(code,m);
 79                 hm[cur^1].push(encode(code,m),hm[cur].f[k]);
 80             }
 81         }
 82         else if(left || up){
 83             int t = left + up;
 84             if(maze[i][j+1]){
 85                 code[j-1]=0;
 86                 code[j]=t;
 87                 hm[cur^1].push(encode(code,m),hm[cur].f[k]);
 88             }
 89             if(maze[i+1][j]){
 90                 code[j-1]=t;
 91                 code[j]=0;
 92                 if(j==m)shift(code,m);
 93                 hm[cur^1].push(encode(code,m),hm[cur].f[k]);
 94             }
 95         }
 96         else{//无插头,则构造新的连通块
 97             if(maze[i][j+1]&&maze[i+1][j]){
 98                 code[j-1]=code[j]=13;
 99                 hm[cur^1].push(encode(code,m),hm[cur].f[k]);
100             }
101         }
102     }
103 }
104 void dpblock(int i,int j,int cur){
105     for(int k=0;k<hm[cur].sz;k++){
106         decode(code,m,hm[cur].state[k]);
107         code[j-1]=code[j]=0;
108         if(j==m)shift(code,m);
109         hm[cur^1].push(encode(code,m),hm[cur].f[k]);
110     }
111 }
112 char str[maxd];
113 void init(){
114     memset(maze,0,sizeof(maze));
115     ex=0;
116     for(int i=1;i<=n;i++){
117         scanf("%s",str+1);
118         for(int j=1;j<=m;j++){
119             if(str[j]=='.'){// 无障碍
120                 ex=i,ey=j;
121                 maze[i][j]=1;
122             }
123         }
124     }
125 }
126 void solve(){
127     int cur=0;
128     ll ans=0;
129     hm[0].clear();
130     hm[0].push(0,1);
131     for(int i=1;i<=n;i++)
132         for(int j=1;j<=m;j++){
133             hm[cur^1].clear();
134             if(maze[i][j])dpblank(i,j,cur);
135             else dpblock(i,j,cur);
136             cur^=1;
137         }
138     for(int i=0;i<hm[cur].sz;i++)
139         ans+=hm[cur].f[i];
140     printf("%I64d\n",ans);
141 }
142 int main(){
143     while(~scanf("%d%d",&n,&m)){
144         init();
145         if(ex==0)puts("0");// 没有空的格子
146         else solve();
147     }
148     return 0;
149 }
View Code

100+ms的版本(改编自那个链接里的。。。。):

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <string>
  7 #include <vector>
  8 #include <queue>
  9 #include <set>
 10 using namespace std;
 11 
 12 #define ll long long
 13 #define inf 0x3f3f3f3f
 14 #define eps 1e-8
 15 
 16 #define maxd 15
 17 #define HASH 100007
 18 #define STATE 1000010
 19 
 20 int n,m;
 21 int maze[maxd][maxd],code[maxd];
 22 int ch[maxd];//最小表示法使用
 23 int ex,ey;//最后一个非障碍格子的坐标
 24 struct HASHMAP{
 25     int head[HASH],nxt[STATE],sz;
 26     ll state[STATE];
 27     ll f[STATE];
 28     void clear(){sz=0;memset(head,-1,sizeof(head));}
 29     void push(ll st,ll ans){
 30         int h=st%HASH;
 31         for(int i=head[h];i!=-1;i=nxt[i])
 32             if(state[i]==st){
 33                 f[i]+=ans;
 34                 return;
 35             }
 36         state[sz]=st;
 37         f[sz]=ans;
 38         nxt[sz]=head[h];
 39         head[h]=sz++;
 40     }
 41 }hm[2];
 42 void decode(int *code,int m,ll    st){
 43     for(int i=0;i<=m;++i)code[i]=st&3,st>>=2;
 44 }
 45 ll encode(int *code,int m){//最小表示法
 46     ll st=0;
 47     for(int i=m;i>=0;--i)
 48         st=st<<2|code[i];
 49     return st;
 50 }
 51 void shift(int *code,int m){
 52     for(int i=m;i>0;i--)code[i]=code[i-1];
 53     code[0]=0;
 54 }
 55 void dpblank(int i,int j,int cur){
 56     for(int k=0;k<hm[cur].sz;k++){
 57         decode(code,m,hm[cur].state[k]);
 58         int left = code[j-1],up = code[j];
 59         if(left&&up){
 60             if(left==2 && up==1){// 只能出现在最后一个非障碍格子
 61                 if(i==ex&&j==ey){
 62                     code[j-1]=code[j]=0;
 63                     ll tmp = encode(code,m);
 64                     if(j==m)tmp<<=2;
 65                     hm[cur^1].push(tmp,hm[cur].f[k]);
 66                 }
 67             }
 68             else{//不在同一个连通分量则合并
 69                 if(left==1 && up==1){//  ...(...(...))... ==> ...(...)...##...
 70                     for(int jj=j-1,cnt=0;jj>=0;--jj){
 71                         if(code[jj]==1)++cnt;
 72                         else if(code[jj]==2)--cnt;
 73                         if(cnt==0){code[jj]=3-code[jj];break;}
 74                     }
 75                     code[j-1]=code[j]=0;
 76                 }
 77                 else if(left==2 && up==2){//  ...((...)...)... ==> ...##...(...)...
 78                     for(int jj=j,cnt=0;jj<=m;++jj){
 79                         if(code[jj]==1)++cnt;
 80                         else if(code[jj]==2)--cnt;
 81                         if(cnt==0){code[jj]=3-code[jj];break;}
 82                     }
 83                     code[j-1]=code[j]=0;
 84                 }
 85                 else if(left==1 && up==2){// ...(...)(...)... ==> ...(...##...)...
 86                     code[j-1]=code[j]=0;
 87                 }
 88                 if(j==m)shift(code,m);
 89                 hm[cur^1].push(encode(code,m),hm[cur].f[k]);
 90             }
 91         }
 92         else if(left || up){
 93             int t = left | up;
 94             if(maze[i][j+1]){
 95                 code[j-1]=0;
 96                 code[j]=t;
 97                 hm[cur^1].push(encode(code,m),hm[cur].f[k]);
 98             }
 99             if(maze[i+1][j]){
100                 code[j-1]=t;
101                 code[j]=0;
102                 if(j==m)shift(code,m);
103                 hm[cur^1].push(encode(code,m),hm[cur].f[k]);
104             }
105         }
106         else{//无插头,则构造新的连通块
107             if(maze[i][j+1]&&maze[i+1][j]){
108                 code[j-1]=2,code[j]=1;
109                 hm[cur^1].push(encode(code,m),hm[cur].f[k]);
110             }
111         }
112     }
113 }
114 void dpblock(int i,int j,int cur){
115     for(int k=0;k<hm[cur].sz;k++){
116         decode(code,m,hm[cur].state[k]);
117         code[j-1]=code[j]=0;
118         if(j==m)shift(code,m);
119         hm[cur^1].push(encode(code,m),hm[cur].f[k]);
120     }
121 }
122 char str[maxd];
123 void init(){
124     memset(maze,0,sizeof(maze));
125     ex=0;
126     for(int i=1;i<=n;i++){
127         scanf("%s",str+1);
128         for(int j=1;j<=m;j++){
129             if(str[j]=='.'){// 无障碍
130                 ex=i,ey=j;
131                 maze[i][j]=1;
132             }
133         }
134     }
135 }
136 void solve(){
137     int cur=0;
138     ll ans=0;
139     hm[0].clear();
140     hm[0].push(0,1);
141     for(int i=1;i<=n;i++)
142         for(int j=1;j<=m;j++){
143             hm[cur^1].clear();
144             if(maze[i][j])dpblank(i,j,cur);
145             else dpblock(i,j,cur);
146             cur^=1;
147         }
148     for(int i=0;i<hm[cur].sz;i++)
149         ans+=hm[cur].f[i];
150     printf("%I64d\n",ans);
151 }
152 int main(){
153     while(~scanf("%d%d",&n,&m)){
154         init();
155         if(ex==0)puts("0");// 没有空的格子
156         else solve();
157     }
158     return 0;
159 }
View Code

转载于:https://www.cnblogs.com/nextbin/p/3707473.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
众所周知,人工智能是当前最热门的话题之一, 计算机技术与互联网技术的快速发展更是将对人工智能的研究推向一个新的高潮。 人工智能是研究模拟和扩展人类智能的理论与方法及其应用的一门新兴技术科学。 作为人工智能核心研究领域之一的机器学习, 其研究动机是为了使计算机系统具有人的学习能力以实现人工智能。 那么, 什么是机器学习呢? 机器学习 (Machine Learning) 是对研究问题进行模型假设,利用计算机从训练据中学习得到模型参,并最终对据进行预测和分析的一门学科。 机器学习的用途 机器学习是一种通用的据处理技术,其包含了大量的学习算法。不同的学习算法在不同的行业及应用中能够表现出不同的性能和优势。目前,机器学习已成功地应用于下列领域: 互联网领域----语音识别、搜索引擎、语言翻译、垃圾邮件过滤、自然语言处理等 生物领域----基因序列分析、DNA 序列预测、蛋白质结构预测等 自动化领域----人脸识别、无人驾驶技术、图像处理、信号处理等 金融领域----证券市场分析、信用卡欺诈检测等 医学领域----疾病鉴别/诊断、流行病爆发预测等 刑侦领域----潜在犯罪识别与预测、模拟人工智能侦探等 新闻领域----新闻推荐系统等 游戏领域----游戏战略规划等 从上述所列举的应用可知,机器学习正在成为各行各业都会经常使用到的分析工具,尤其是在各领域据量爆炸的今天,各行业都希望通过据处理与分析手段,得到据中有价值的信息,以便明确客户的需求和指引企业的发展。
众所周知,人工智能是当前最热门的话题之一, 计算机技术与互联网技术的快速发展更是将对人工智能的研究推向一个新的高潮。 人工智能是研究模拟和扩展人类智能的理论与方法及其应用的一门新兴技术科学。 作为人工智能核心研究领域之一的机器学习, 其研究动机是为了使计算机系统具有人的学习能力以实现人工智能。 那么, 什么是机器学习呢? 机器学习 (Machine Learning) 是对研究问题进行模型假设,利用计算机从训练据中学习得到模型参,并最终对据进行预测和分析的一门学科。 机器学习的用途 机器学习是一种通用的据处理技术,其包含了大量的学习算法。不同的学习算法在不同的行业及应用中能够表现出不同的性能和优势。目前,机器学习已成功地应用于下列领域: 互联网领域----语音识别、搜索引擎、语言翻译、垃圾邮件过滤、自然语言处理等 生物领域----基因序列分析、DNA 序列预测、蛋白质结构预测等 自动化领域----人脸识别、无人驾驶技术、图像处理、信号处理等 金融领域----证券市场分析、信用卡欺诈检测等 医学领域----疾病鉴别/诊断、流行病爆发预测等 刑侦领域----潜在犯罪识别与预测、模拟人工智能侦探等 新闻领域----新闻推荐系统等 游戏领域----游戏战略规划等 从上述所列举的应用可知,机器学习正在成为各行各业都会经常使用到的分析工具,尤其是在各领域据量爆炸的今天,各行业都希望通过据处理与分析手段,得到据中有价值的信息,以便明确客户的需求和指引企业的发展。
众所周知,人工智能是当前最热门的话题之一, 计算机技术与互联网技术的快速发展更是将对人工智能的研究推向一个新的高潮。 人工智能是研究模拟和扩展人类智能的理论与方法及其应用的一门新兴技术科学。 作为人工智能核心研究领域之一的机器学习, 其研究动机是为了使计算机系统具有人的学习能力以实现人工智能。 那么, 什么是机器学习呢? 机器学习 (Machine Learning) 是对研究问题进行模型假设,利用计算机从训练据中学习得到模型参,并最终对据进行预测和分析的一门学科。 机器学习的用途 机器学习是一种通用的据处理技术,其包含了大量的学习算法。不同的学习算法在不同的行业及应用中能够表现出不同的性能和优势。目前,机器学习已成功地应用于下列领域: 互联网领域----语音识别、搜索引擎、语言翻译、垃圾邮件过滤、自然语言处理等 生物领域----基因序列分析、DNA 序列预测、蛋白质结构预测等 自动化领域----人脸识别、无人驾驶技术、图像处理、信号处理等 金融领域----证券市场分析、信用卡欺诈检测等 医学领域----疾病鉴别/诊断、流行病爆发预测等 刑侦领域----潜在犯罪识别与预测、模拟人工智能侦探等 新闻领域----新闻推荐系统等 游戏领域----游戏战略规划等 从上述所列举的应用可知,机器学习正在成为各行各业都会经常使用到的分析工具,尤其是在各领域据量爆炸的今天,各行业都希望通过据处理与分析手段,得到据中有价值的信息,以便明确客户的需求和指引企业的发展。
众所周知,人工智能是当前最热门的话题之一, 计算机技术与互联网技术的快速发展更是将对人工智能的研究推向一个新的高潮。 人工智能是研究模拟和扩展人类智能的理论与方法及其应用的一门新兴技术科学。 作为人工智能核心研究领域之一的机器学习, 其研究动机是为了使计算机系统具有人的学习能力以实现人工智能。 那么, 什么是机器学习呢? 机器学习 (Machine Learning) 是对研究问题进行模型假设,利用计算机从训练据中学习得到模型参,并最终对据进行预测和分析的一门学科。 机器学习的用途 机器学习是一种通用的据处理技术,其包含了大量的学习算法。不同的学习算法在不同的行业及应用中能够表现出不同的性能和优势。目前,机器学习已成功地应用于下列领域: 互联网领域----语音识别、搜索引擎、语言翻译、垃圾邮件过滤、自然语言处理等 生物领域----基因序列分析、DNA 序列预测、蛋白质结构预测等 自动化领域----人脸识别、无人驾驶技术、图像处理、信号处理等 金融领域----证券市场分析、信用卡欺诈检测等 医学领域----疾病鉴别/诊断、流行病爆发预测等 刑侦领域----潜在犯罪识别与预测、模拟人工智能侦探等 新闻领域----新闻推荐系统等 游戏领域----游戏战略规划等 从上述所列举的应用可知,机器学习正在成为各行各业都会经常使用到的分析工具,尤其是在各领域据量爆炸的今天,各行业都希望通过据处理与分析手段,得到据中有价值的信息,以便明确客户的需求和指引企业的发展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值