HDU 4433 locker(SPFA+DP)

题目链接

去年区域赛的题目,早就看过题目了,又是过了好久了。。。

这题状态转移,一看就知道应该是 线性的那种,不过细节真的不好处理,一直没想出怎么搞,期间也看过题解,好像没太看懂。。。

dp[i][j]表示前i位相同,i之后两位为j的最小转动次数。

例如dp[i][x*10+y]  i+3位 为z(初始数字),x y z 转化为 ax ay az,ax肯定是第二个串的第i位,后两位随便就可以。

只要 预处理 xyz 转化为axayaz的情况,就行了。dp[0]初始化,100位直接Floyd,其他的1000位的预处理,用spfa搞的。

预处理写的很长。。

  1 #include <cstring>

  2 #include <cstdio>

  3 #include <string>

  4 #include <iostream>

  5 #include <algorithm>

  6 #include <vector>

  7 #include <queue>

  8 using namespace std;

  9 #define INF 10000000

 10 char s1[1200],s2[1200];

 11 int dp[1010][110];

 12 int mp[1010][1010];

 13 int dis[1010];

 14 int in[1010];

 15 int p[101][101];

 16 int n1[1010],n2[1010];

 17 int a[12] = {1,0,0,1,0,1,-1,0,0,-1,0,-1};

 18 int b[12] = {0,1,0,1,1,1,0,-1,0,-1,-1,-1};

 19 int c[12] = {0,0,1,0,1,1,0,0,-1,0,-1,-1};

 20 void spfa(int key)

 21 {

 22     int x,y,z,i,ax,ay,az,u,v;

 23     queue <int> que;

 24     for(i = 0;i < 1000;i ++)

 25     {

 26         dis[i] = INF;

 27         in[i] = 0;

 28     }

 29     in[key] = 1;

 30     dis[key] = 0;

 31     que.push(key);

 32     while(!que.empty())

 33     {

 34         u = que.front();

 35         in[u] = 0;

 36         que.pop();

 37         x = (u/100)%10;

 38         y = (u/10)%10;

 39         z = u%10;

 40         for(i = 0;i < 12;i ++)

 41         {

 42             ax = (x+a[i]+10)%10;

 43             ay = (y+b[i]+10)%10;

 44             az = (z+c[i]+10)%10;

 45             v = ax*100+ay*10+az;

 46             if(dis[v] > dis[u] + 1)

 47             {

 48                 if(!in[v])

 49                 {

 50                     in[v] = 1;

 51                     que.push(v);

 52                 }

 53                 dis[v] = dis[u] + 1;

 54             }

 55         }

 56     }

 57     for(i = 0;i < 1000;i ++)

 58     mp[key][i] = dis[i];

 59     return ;

 60 }

 61 int main()

 62 {

 63     int i,j,len,x,y,z,k,temp;

 64     for(i = 0;i < 100;i ++)

 65     {

 66         for(j = 0;j < 100;j ++)

 67         p[i][j] = INF;

 68         p[i][i] = 0;

 69     }

 70     for(i = 0;i < 100;i ++)

 71     {

 72         x = (i/10)%10;

 73         y = i%10;

 74         p[x][(y+1)%10] = 1;

 75         p[(y+1)%10][x] = 1;

 76         p[(x+1)%10][y] = 1;

 77         p[y][(x+1)%10] = 1;

 78         p[(x+1)%10][(y+1)%10] = 1;

 79         p[(y+1)%10][(x+1)%10] = 1;

 80     }

 81     for(i = 0;i < 100;i ++)

 82     {

 83         for(j = 0;j < 100;j ++)

 84         {

 85             for(k = 0;k < 100;k ++)

 86             {

 87                 if(p[j][k] > p[j][i] + p[i][k])

 88                 p[j][k] = p[j][i] + p[i][k];

 89             }

 90         }

 91     }

 92     for(i = 0;i < 1000;i ++)

 93     {

 94         spfa(i);

 95     }

 96     while(scanf("%s%s",s1,s2)!=EOF)

 97     {

 98         len = strlen(s1);

 99         for(i = 1;i <= len;i ++)

100         {

101             n1[i] = s1[i-1] - '0';

102             n2[i] = s2[i-1] - '0';

103         }

104         for(i = 0;i <= len;i ++)

105         {

106             for(j = 0;j < 100;j ++)

107             dp[i][j] = INF;

108         }

109         n1[len+1] = n2[len+1] = 0;

110         n1[len+2] = n2[len+2] = 0;

111         temp = n1[1] * 10 + n1[2];

112         for(i = 0;i < 100;i ++)

113         {

114             dp[0][i] = p[temp][i];

115         }

116         for(i = 0;i < len;i ++)

117         {

118             z = n1[i+3];

119             for(j = 0;j < 100;j ++)

120             {

121                 x = (j/10)%10;

122                 y = j%10;

123                 for(k = 0;k < 100;k ++)

124                 {

125                     if(dp[i+1][k] > dp[i][j] + mp[j*10+z][n2[i+1]*100+k])

126                     dp[i+1][k] = dp[i][j] + mp[j*10+z][n2[i+1]*100+k];

127                 }

128             }

129         }

130         printf("%d\n",dp[len][0]);

131     }

132     return 0;

133 }

 

你可能感兴趣的:(Lock)