古韵之鹊桥相会

jdoj1497-vijos1406古韵之鹊桥相会

    题目大意:给你一个m行n列的字母矩阵,有一个人,每一次可以将几个联通块打没。联通块的定义是两个挨着的字母,如果他们两个相同,那么就说他们两个是联通的。求:从上面到下面,最少打几次才可以到达。

    注释:n,m<21。

      想法:先说网上的主流题解。大部分的处理方式就是bfs求出联通块,将每一个联通块缩成一个点。最上面有一个大源点,下面有一个大源点,然后从上面到下面跑Dijkstra即可。在此说一说我yy的解法(网上好像也有)。就是dfs,暴力求出每两个点之间是否连通,设数组map[i1][j1][i2][j1]表示点(i1,j1)到点(i2,j2)的最短路。两个单独的挨着的点相同就是0,相异就是1,最后跑floyd 即可。时间复杂度$8\cdot 10^6$可过。

    最后,附上丑陋的代码... ...

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 char s[25][25];
 6 int map[25][25][25][25];
 7 int n,m;
 8 void dfs(int a,int b)
 9 {
10     if(a==m)
11     {
12         if(b==n) return;
13         else
14         {
15             if(s[a][b+1]==s[a][b]) map[a][b][a][b+1]=map[a][b+1][a][b]=0;
16             else map[a][b][a][b+1]=map[a][b+1][a][b]=1;
17             dfs(a,b+1);
18         }
19     }
20     else
21     {
22         if(b==n)
23         {
24             if(s[a+1][b]==s[a][b]) map[a][b][a+1][b]=map[a+1][b][a][b]=0;
25             else map[a][b][a+1][b]=map[a+1][b][a][b]=1;
26             dfs(a+1,1);
27         }
28         else
29         {
30             if(s[a+1][b]==s[a][b]) map[a][b][a+1][b]=map[a+1][b][a][b]=0;
31             else map[a][b][a+1][b]=map[a+1][b][a][b]=1;
32             if(s[a][b+1]==s[a][b]) map[a][b][a][b+1]=map[a][b+1][a][b]=0;
33             else map[a][b][a][b+1]=map[a][b+1][a][b]=1;
34             dfs(a,b+1);
35         }
36     }
37 }
38 int main()
39 {
40     scanf("%d%d",&m,&n);
41     if(m==1)
42     {
43         printf("1\n");
44         return 0;
45     }
46     for(int i=1;i<=m;i++)
47     {
48         scanf("%s",s[i]+1);
49     }
50     memset(map,0x3f,sizeof(map));
51     dfs(1,1);
52     // for(int i=1;i<=m;i++) 
53     // {
54     //     for(int j=1;j<=n;j++)
55     //     {
56     //         printf("%d ",map[i][j][i+1][j]);
57     //     }
58     //     puts("");
59     // }
60     for(int k1=1;k1<=m;k1++) for(int k2=1;k2<=n;k2++)//floyd。
61     for(int i1=1;i1<=m;i1++) for(int i2=1;i2<=n;i2++)
62     for(int j1=1;j1<=m;j1++) for(int j2=1;j2<=n;j2++)
63         map[i1][i2][j1][j2]=min(map[i1][i2][k1][k2]+map[k1][k2][j1][j2],map[i1][i2][j1][j2]);
64     int minn=0x7f7f7f7f;//统计答案
65     for(int head=1;head<=n;head++)
66     {
67         for(int foot=1;foot<=n;foot++)
68         {    
69             // printf("%d ",map[1][head][m][foot]);
70             minn=min(map[1][head][m][foot],minn);
71         }
72         // puts("");
73     }
74     printf("%d",minn+1);//由于我从最上面到第一排的点并没有统计,所以需要+1,这也就是我为什么开始特判掉只有1行的情况。
75 }

 

    小结,错误:忘记特判掉1了,这就gg了。

 

 

转载于:https://www.cnblogs.com/ShuraK/p/8270236.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值