zoukankan      html  css  js  c++  java
  • poj3592 强连通+记忆化搜索

    题意:有一片 n*m 的矿地,每一格有矿、或这传送门、或者挡路岩石。除了岩石不能走以外,其他的格子都能够向右或向下走,走到一个非岩石的格子。对于每一个矿点,经过它就能得到它的所有矿石,而对于每一个传送门,你可以选择传送或者不传送,向右或向下继续走(传送门送达点也可能是岩石),按从上到下、从左到右的顺序对于每一个传送门给定一个传送点。问最多能够获得多少矿石。

    对于这样一张图,我们能够发现,有一些点,由于传送门的存在,一定可以相互到达,那么这些点可以按强连通缩点,之后对于有向无环图就可以很轻松地用记忆化搜索得到最大值了。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stack>
      4 #include<queue>
      5 using namespace std;
      6 
      7 const int maxn=1605;
      8 const int maxm=1e5;
      9 
     10 char s[45][45];
     11 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2];
     12 int n,t,scccnt;
     13 int stx[maxn],low[maxn],scc[maxn],num[maxn],v[maxn];
     14 int dp[maxn];
     15 stack<int>S;
     16 
     17 int max(int a,int b){return a>b?a:b;}
     18 
     19 void init(){
     20     memset(head,-1,sizeof(head));
     21     size[0]=size[1]=0;
     22     memset(num,0,sizeof(num));
     23     memset(dp,-1,sizeof(dp));
     24 }
     25 
     26 void add(int a,int b,int c=0){
     27     point[c][size[c]]=b;
     28     nxt[c][size[c]]=head[c][a];
     29     head[c][a]=size[c]++;
     30 }
     31 
     32 void dfs(int s){
     33     stx[s]=low[s]=++t;
     34     S.push(s);
     35     for(int i=head[0][s];~i;i=nxt[0][i]){
     36         int j=point[0][i];
     37         if(!stx[j]){
     38             dfs(j);
     39             low[s]=min(low[s],low[j]);
     40         }
     41         else if(!scc[j]){
     42             low[s]=min(low[s],stx[j]);
     43         }
     44     }
     45     if(low[s]==stx[s]){
     46         scccnt++;
     47         while(1){
     48             int u=S.top();S.pop();
     49             scc[u]=scccnt;
     50             num[scccnt]+=v[u];
     51             if(s==u)break;
     52         }
     53     }
     54 }
     55 
     56 void setscc(){
     57     memset(stx,0,sizeof(stx));
     58     memset(scc,0,sizeof(scc));
     59     t=scccnt=0;
     60     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
     61     for(int i=1;i<=n;++i){
     62         for(int j=head[0][i];~j;j=nxt[0][j]){
     63             int k=point[0][j];
     64             if(scc[i]!=scc[k]){
     65                 add(scc[i],scc[k],1);
     66             }
     67         }
     68     }
     69 }
     70 
     71 int Dp(int s){
     72     if(~dp[s])return dp[s];
     73     int maxx=0;
     74     for(int i=head[1][s];~i;i=nxt[1][i]){
     75         maxx=max(maxx,Dp(point[1][i]));
     76     }
     77     return dp[s]=num[s]+maxx;
     78 }
     79 
     80 int main(){
     81     int T;
     82     scanf("%d",&T);
     83     while(T--){
     84         int m,l;
     85         scanf("%d%d",&l,&m);
     86         n=m*l;
     87         init();
     88         for(int i=1;i<=l;++i)scanf("%s",s[i]+1);
     89         int a,b;
     90         for(int i=1;i<=l;++i){
     91             for(int j=1;j<=m;++j){
     92                 int p=(i-1)*m+j;
     93                 if(s[i][j]>='0'&&s[i][j]<='9'){
     94                     v[p]=s[i][j]-'0';
     95                 }
     96                 else v[p]=0;
     97                 if(s[i][j]!='#'){
     98                     if(i+1<=l&&s[i+1][j]!='#'){
     99                         add(p,p+m);
    100                     }
    101                     if(j+1<=m&&s[i][j+1]!='#'){
    102                         add(p,p+1);
    103                     }
    104                 }
    105                 if(s[i][j]=='*'){
    106                     scanf("%d%d",&a,&b);
    107                     a++;
    108                     b++;
    109                     if(s[a][b]!='#'){
    110                         int p1=(a-1)*m+b;
    111                         add(p,p1);
    112                     }
    113                 }
    114             }
    115         }
    116         setscc();
    117         printf("%d
    ",Dp(scc[1]));
    118     }
    119     return 0;
    120 }
    View Code
  • 相关阅读:
    Java后台实现方法
    解决横屏下锁屏,再次解锁界面显示异常-一屏下显示反复两个界面
    java平台利用jsoup开发包,抓取优酷视频播放地址与图片地址等信息。
    用C++实现一个Log系统
    LeetCode 3_Longest Substring Without Repeating Characters
    跟着实例学习设计模式(7)-原型模式prototype(创建型)
    XStream 数组(List)输出结构
    【Cocos2d-x 3.0 基础系列一】 各类回调函数写法汇总
    机房收费系统验收小结(一)
    动态隐藏/显示系统状态栏
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4817682.html
Copyright © 2011-2022 走看看