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 }

 

posted @ 2013-09-02 11:39  Naix_x  阅读(491)  评论(0编辑  收藏  举报