题目链接: http://poj.org/problem?id=3592
题目大意:
给定一个n*m的地图,有0-9表示某个格子上的value,‘*’表示该格子上有个时空门,可直接到指定的某个格子(可以自行选择是否使用时空门),‘#’表示该格子无法使用,某个格子的value只能被计算一次,问从起点(规定为左上角,我一直把northwest看成了右上角,伤不起)出发,每次只能往下走一格或往右走一格,最多能得到多大的value。
分析:
首先根据给定的关系建图,又因为有时空门的存在,所以必须缩点,
对缩点后的图进行拓扑排序之后再dp,即可求得最长路。
(PS: 这题我看了discuss,发现思路什么的对了,就是一点,起点我自己看成了右上角,伤不起啊~!~)
代码(好像我的比较冗长的):
poj3592
1 /*3592 Accepted 428K 0MS C++ 4222B 2012-06-09 16:18:12*/ 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <iostream> 6 #include <algorithm> 7 #include <vector> 8 using namespace std; 9 10 #define mpair make_pair 11 #define pii pair<int,int> 12 #define MM(a,b) memset(a,b,sizeof(a)); 13 typedef long long lld; 14 typedef unsigned long long u64; 15 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;} 16 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;} 17 #define maxn 1640 18 #define maxm 50 19 20 int n,m,k, nv; 21 int f[maxm][maxm]; 22 char ch[maxm][maxm]; 23 24 vector<int>g[maxn], adj[maxn]; 25 int mark[maxm][maxm]; 26 pii a[maxn], fp[maxn]; 27 28 void Read(){ 29 int i,j,x,y; 30 scanf("%d %d\n", &n, &m); 31 for(i=0;i<n;++i) 32 for(j=0;j<m;++j){ 33 f[i][j]= i*m + j + 1; 34 fp[i*m+j+1]= pii( i, j ); 35 } 36 nv= n*m; 37 38 k= 0; 39 for(i=0;i<n;++i){ 40 for(j=0;j<m;++j){ 41 scanf("%c", &ch[i][j]); 42 if( '*' == ch[i][j] ) 43 mark[i][j]= ++k; 44 } 45 getchar(); 46 } 47 48 for(i=1;i<=k;++i){ 49 scanf("%d%d", &x, &y); 50 a[i]= pii( x, y ); 51 } 52 } 53 54 void build_graph(){ 55 int i,j; 56 for(i=1;i<=nv;++i) g[i].clear(); 57 for(i=0;i<n;++i){ 58 for(j=0;j<m;++j){ 59 if( '#' == ch[i][j] ) continue; 60 61 if( i+1<n && '#'!=ch[i+1][j] ){ /// go down; 62 g[ f[i][j] ].push_back( f[i+1][j] ); 63 } 64 if( j+1<m && '#'!=ch[i][j+1] ){ /// go left; 65 g[ f[i][j] ].push_back( f[i][j+1] ); 66 } 67 if( '*' == ch[i][j] ){ /// can use magic power; 68 int t= mark[i][j]; 69 int x= a[t].first, y= a[t].second; 70 if( '#' != ch[x][y] ) /// 71 g[ f[i][j] ].push_back( f[x][y] ); 72 } 73 } 74 } 75 } 76 77 int c[maxn]; /// each block's sum-value; 78 79 int Bcnt, Index, Top; 80 int low[maxn], dfn[maxn], stack[maxn], belong[maxn]; 81 bool inq[maxn]; 82 void Init_tarjan(){ 83 Bcnt= Index= Top= 0; 84 for(int i=1;i<=nv;++i) low[i]= dfn[i]= inq[i]= 0; 85 } 86 void Tarjan(int u){ 87 stack[++Top]= u; 88 inq[u]= 1; 89 low[u]= dfn[u]= ++Index; 90 for(int i=0;i<g[u].size();++i){ 91 int v= g[u][i]; 92 if( !dfn[v] ){ 93 Tarjan( v ); 94 up_min( low[u], low[v] ); 95 } 96 else if( inq[v] ) 97 up_min( low[u], dfn[v] ); 98 } 99 if( low[u]==dfn[u] ){ 100 ++Bcnt; 101 int v; 102 do{ 103 v= stack[Top--]; 104 inq[v]= 0; 105 belong[v]= Bcnt; 106 int x= fp[v].first, y= fp[v].second; 107 if( '1'<=ch[x][y] && ch[x][y]<='9' ) 108 c[Bcnt]+= ch[x][y]-'0'; 109 }while(u!=v); 110 } 111 } 112 113 int in[maxn]; 114 void build2(int u){ 115 inq[u]= 1; 116 for(int i=0;i<g[u].size();++i){ 117 int v= g[u][i]; 118 if( belong[v] != belong[u] ){ 119 adj[ belong[u] ].push_back( belong[v] ); 120 ++in[ belong[v] ]; 121 } 122 if( !inq[v] ) build2(v); /// here!!!!!!!!!!!!!!!!!!!; 123 } 124 } 125 126 int *que; /// 127 int dp[maxn]; 128 int Topsort(){ 129 int i,head=0,tail=0; 130 fill( dp, dp+1+Bcnt, 0 ); 131 /// for(i=1;i<=Bcnt;++i) if( in[i]==0 ) { que[tail++]= i; dp[i]= c[i]; } 132 que[tail++]= belong[1]; ///!!!!!!!!!!!!! 133 dp[belong[1]]= c[belong[1]]; 134 135 while( head<tail ){ 136 int u= que[head++]; 137 for(int i=0;i<adj[u].size();++i){ 138 int v= adj[u][i]; 139 if( --in[v] == 0 ) 140 que[tail++]= v; 141 } 142 } 143 144 for(i=0;i<tail;++i){ 145 int u= que[i]; 146 for(int j=0;j<adj[u].size();++j){ 147 int v= adj[u][j]; 148 up_max( dp[v], dp[u]+c[v] ); 149 } 150 } 151 152 int ans= 0; 153 for(i=0;i<tail;++i) up_max( ans, dp[ que[i] ] ); /// que[i]; 154 return ans; 155 } 156 157 int solve(){ 158 build_graph(); 159 Init_tarjan(); 160 fill( c, c+nv+1, 0 ); 161 Tarjan(1); /// 162 163 for(int i=1;i<=Bcnt;++i) adj[i].clear(), inq[i]= 0, in[i]= 0; 164 build2(1); 165 166 que= stack; 167 return Topsort(); 168 } 169 170 int main() 171 { 172 //freopen("poj3592.in","r",stdin); 173 int T; 174 cin>>T; 175 while(T--){ 176 Read(); 177 cout<< solve() <<endl; 178 } 179 }