zoukankan      html  css  js  c++  java
  • FOJ1977 Pandora adventure 插头DP

      题目链接:http://acm.fzu.edu.cn/problem.php?pid=1977

      题目(备份):

    View Code
    Problem Description
    The pollution of the earth is so serious that people can not survive any more. Fortunately, people have found a new planet that maybe has life, and we call it "Pandora Planet".
    
    
    Leonardo Da Vinci is the only astronaut on the earth. He will be sent to the Pandora Planet to gather some plant specimens and go back. The plant specimen is important to the people to decide whether the planet is fit to live or not.
    
    
    Assuming that Da Vinci can only move in an N×M grid. The positions of the plant specimens he wants to collect are all marked by the satellite. His task is to find a path to collect all the plant specimens and return to the spaceship. There are some savage beasts in the planet. Da Vinci can not investigate the grid with the savage beast. These grids are also marked by the satellite. In order to save time Da Vinci could only visit each grid exactly once and also return to the start grid, that is, you can not visit a grid twice except the start grid. You should note that you can choose any grid as the start grid.
    
    
    Now he wants to know the number of different paths he can collect all the plant specimens. We only care about the path and ignore where the start grid is, so the two paths in Figure 1 are considered as the same.
    
    
    Figure 1
     Input
    The first line of the input contains an integer T (T≤100), indicating the number of cases. Each case begins with a line containing two integers N and M (1≤N, M≤12), the size of the planet is N×M. Each of the following N lines contains M characters Gij(1≤i≤N, 1≤j≤M), Gij denotes the status of the grid in row i and column j, where 'X' denotes the grid with savage beast, '*' denotes the safe grid that you can decide to go or not, 'O' denotes the plant specimen you should collect. We guarantee that there are at least three plant specimens in the map.
    
     Output
    For each test case, print a line containing the test case number (beginning with 1) and the number of different paths he can collect all the plant specimens. You can make sure that the answer will fit in a 64-bit signed integer.
    
     Sample Input
    2
    2 2
    OO
    O*
    4 4
    ***O
    XO**
    **O*
    XX**
     Sample Output
    Case 1: 1
    Case 2: 7

      题意是这样的,给你一个地图,其中有些地方必须经过,有些地方不必须经过,有些地方不能经过,求满足的回路数有多少条。在逐格递推的时候统计已经过plant specimens的个数,在和并连通分量的时候,如果plant specimens的个数已经达到总个数,在判断此时状态的环的个数,如果只有一个,那么加入ans,并且不计入下一个格子的状态。

      1 //STATUS:C++_AC_359MS_19832KB
      2 #include<stdio.h>
      3 #include<stdlib.h>
      4 #include<string.h>
      5 #include<math.h>
      6 #include<iostream>
      7 #include<string>
      8 #include<algorithm>
      9 #include<vector>
     10 #include<queue>
     11 #include<stack>
     12 #include<map>
     13 using namespace std;
     14 #define LL long long
     15 #define pii pair<int,int>
     16 #define Max(a,b) ((a)>(b)?(a):(b))
     17 #define Min(a,b) ((a)<(b)?(a):(b))
     18 #define mem(a,b) memset(a,b,sizeof(a))
     19 #define lson l,mid,rt<<1
     20 #define rson mid+1,r,rt<<1|1
     21 const int N=15,INF=0x3f3f3f3f,MOD=4001,STA=8000010;
     22 const double DNF=1e13;
     23 
     24 int g[N][N],code[N],ma[N];
     25 int T,n,m,ex,ey,sumo,cnto;
     26 LL ans;
     27 
     28 struct Hash{     //Hash表,MOD为表长,STA为表大小
     29     int first[MOD],next[STA],size;
     30     LL f[STA],sta[STA];
     31     void init(){
     32         size=0;
     33         mem(first,-1);
     34     }
     35     void add(LL st,LL ans){
     36         int i,u=st%MOD;
     37         for(i=first[u];i!=-1;i=next[i]){
     38             if(sta[i]==st){
     39                 f[i]+=ans;
     40                 return;
     41             }
     42         }
     43         sta[size]=st;
     44         f[size]=ans;
     45         next[size]=first[u];
     46         first[u]=size++;
     47     }
     48 }hs[2];
     49 
     50 void shift(int p)    //换行移位
     51 {
     52     int k;
     53     LL sta;
     54     for(k=0;k<hs[!p].size;k++){
     55         sta=hs[!p].sta[k]<<3;
     56         hs[p].add(sta,hs[!p].f[k]);
     57     }
     58 }
     59 
     60 LL getsta()   //最小表示法
     61 {
     62     LL i,cnt=1,sta=0;
     63     mem(ma,-1);
     64     ma[0]=0;
     65     for(i=0;i<=m;i++){
     66         if(ma[code[i]]==-1)ma[code[i]]=cnt++;
     67         code[i]=ma[code[i]];
     68         sta|=(LL)code[i]<<(3*i);
     69     }
     70     return sta;
     71 }
     72 
     73 void getcode(LL sta)
     74 {
     75     int i;
     76     for(i=0;i<=m;i++){
     77         code[i]=sta&7;
     78         sta>>=3;
     79     }
     80 }
     81 
     82 void unblock(int i,int j,int p)
     83 {
     84     int k,t;
     85     LL cnt,x,y;
     86     for(k=0;k<hs[!p].size;k++){
     87         getcode(hs[!p].sta[k]);
     88         x=code[j],y=code[j+1];
     89         cnt=hs[!p].f[k];
     90         if(x && y){     //合并连通分量
     91             code[j]=code[j+1]=0;
     92             if(x!=y){
     93                 for(t=0;t<=m;t++)
     94                     if(code[t]==y)code[t]=x;
     95                 hs[p].add(getsta(),cnt);
     96             }
     97             else if(cnto>=sumo){
     98                 int ok=1;
     99                 for(t=0;t<=m;t++){
    100                     if(code[t]){ok=0;break;}
    101                 }
    102                 if(ok)ans+=cnt;
    103             }
    104         }
    105         else if(x&&!y || !x&&y){   //延续连通分量
    106             t=x?x:y;
    107             if(g[i+1][j]){
    108                 code[j]=t;code[j+1]=0;
    109                 hs[p].add(getsta(),cnt);
    110             }
    111             if(g[i][j+1]){
    112                 code[j]=0;code[j+1]=t;
    113                 hs[p].add(getsta(),cnt);
    114             }
    115         }
    116         else {          //创建新连通分量
    117             if(g[i][j]==1)
    118                 hs[p].add(getsta(),cnt);
    119             if(g[i+1][j] && g[i][j+1]){
    120                 code[j]=code[j+1]=8;
    121                 hs[p].add(getsta(),cnt);
    122             }
    123         }
    124     }
    125 }
    126 
    127 void block(LL j,int p)
    128 {
    129     int k;
    130     for(k=0;k<hs[!p].size;k++){
    131         getcode(hs[!p].sta[k]);
    132         code[j]=code[j+1]=0;
    133         hs[p].add(getsta(),hs[!p].f[k]);
    134     }
    135 }
    136 
    137 LL slove()
    138 {
    139     int i,j,p;
    140     ans=0;cnto=0;
    141     hs[0].init();
    142     hs[p=1].init();
    143     hs[0].add(0,1);
    144     for(i=0;i<n;i++){
    145         for(j=0;j<m;j++){
    146             if(g[i][j]){
    147                 cnto+=g[i][j]==2;
    148                 unblock(i,j,p);
    149             }
    150             else block(j,p);
    151             hs[p=!p].init();
    152         }
    153         shift(p);   //换行移位
    154         hs[p=!p].init();
    155     }
    156     return ans;
    157 }
    158 
    159 int main()
    160 {
    161  //   freopen("in.txt","r",stdin);
    162     int i,j,k=1;
    163     char c;
    164     scanf("%d",&T);
    165     while(T--)
    166     {
    167         scanf("%d%d",&n,&m);
    168         sumo=0;
    169         mem(g,0);
    170         for(i=0;i<n;i++){
    171             for(j=0;j<m;j++){
    172                 scanf(" %c",&c);
    173                 if(c=='O'){
    174                     g[i][j]=2;
    175                     sumo++;
    176                 }
    177                 else if(c=='*')g[i][j]=1;
    178                 else g[i][j]=0;
    179             }
    180         }
    181 
    182         slove();
    183 
    184         printf("Case %d: %I64d\n",k++,ans);
    185     }
    186     return 0;
    187 }
  • 相关阅读:
    学习计划(一)——JavaScript 殷的博客
    学习计划——巩固基础+进阶练习 殷的博客
    第二章:在HTML中使用JavaScript 殷的博客
    W3Cschool学习笔记——CSS教程 殷的博客
    W3Cschool学习笔记——HTML5基础教程 殷的博客
    PS切图篇(一)界面设置 殷的博客
    W3Cschool学习笔记——CSS3教程 殷的博客
    PHP Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING
    css怎么让图片垂直左右居中?(外层div是浮动且按照百分比排列)
    在各浏览器和各分辨率下如何让div内的table垂直水平居中?
  • 原文地址:https://www.cnblogs.com/zhsl/p/2998428.html
Copyright © 2011-2022 走看看