AmazingCounters.com

WC2008游览计划(BZOJ2595)

传送门

 

2595: [Wc2008]游览计划

Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special Judge
[Submit][Status]

Description

Input

第一行有两个整数,N和 M,描述方块的数目。
接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点;
否则表示控制该方块至少需要的志愿者数目。 相邻的整数用 (若干个) 空格隔开,
行首行末也可能有多余的空格。

Output


由 N + 1行组成。第一行为一个整数,表示你所给出的方案
中安排的志愿者总数目。
接下来 N行,每行M 个字符,描述方案中相应方块的情况:
z  ‘_’(下划线)表示该方块没有安排志愿者;
z  ‘o’(小写英文字母o)表示该方块安排了志愿者;
z  ‘x’(小写英文字母x)表示该方块是一个景点;
注:请注意输出格式要求,如果缺少某一行或者某一行的字符数目和要求不
一致(任何一行中,多余的空格都不允许出现) ,都可能导致该测试点不得分。

Sample Input

4 4
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0



Sample Output

6
xoox
___o
___o
xoox

HINT

 对于100%的数据,N,M,K≤10,其中K为景点的数目。输入的所有整数均在[0,2^16]的范围内

Source

Ljcc930提供SPJ

出题者XXOO的真丧病-_-#

写了好长时间了。。比较简单的插头dp。。保存路径也比较简单。。WA了N次是因为。。我把X、O写倒了。。

轮廓线以上的格子表示有没有选中,那么对于一个非景点格子,如果可以不选,那么要么是i-1,j不选 ,要么是i-1,j选了但是轮廓线上存在其他的格子和i-1,j是一个联通块。

Codes:
  1 #include<set>
  2 #include<queue>
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<iostream>
  7 #include<algorithm>
  8 using namespace std;
  9 const int N = 1<<15;
 10 const int Hash = 10007;
 11 #define nxt (cur^1)
 12 #define For(i,n) for(int i=1;i<=n;i++)
 13 #define Rep(i,l,r) for(int i=l;i<=r;i++)
 14 #define Down(i,r,l) for(int i=r;i>=l;i--)
 15  
 16 pair< pair<int,int> ,int > opt[N*110];
 17 int pre[N*110],optot;
 18 int loc,cur,n,m,maze[15][15],ans=1<<30,code[15];
 19 char Ans[15][15];
 20  
 21 struct statedp{
 22     int Loc[N],size,f[N],head[Hash],next[N],st[N];
 23     void clear(){size=0;memset(head,-1,sizeof(head));}
 24     void push(int state,int ans,int last,int x,int y,int kind){
 25         int Key = state % Hash;
 26         for(int p=head[Key];p!=-1;p=next[p])
 27             if(st[p]==state) {  
 28                 if(ans<f[p]) {
 29                     f[p]=ans;pre[Loc[p]]=last;
 30                     opt[Loc[p]]=make_pair(make_pair(x,y),kind);
 31                 }
 32                 return;
 33             }
 34         f[size]=ans;st[size]=state;
 35         Loc[size]=++optot;
 36         pre[optot]=last;opt[optot]=make_pair(make_pair(x,y),kind);
 37         next[size]=head[Key];head[Key]=size++;
 38     }
 39 }dp[2];
 40  
 41 void init(){
 42     scanf("%d%d",&n,&m);
 43     For(i,n)
 44       For(j,m)
 45         scanf("%d",&maze[i][j]);
 46 }
 47  
 48 void decode(int st){
 49     For(i,m) code[i]=st&7,st>>=3;
 50 }
 51  
 52 int encode(){
 53     int st=0,cnt=1,h[10];
 54     memset(h,-1,sizeof(h));
 55     h[0]=0;
 56     Down(i,m,1){
 57         if(h[code[i]]==-1) h[code[i]]=cnt++;
 58         code[i]=h[code[i]];
 59         st = (st<<3)|code[i];
 60     }
 61     return st;
 62 }
 63  
 64 void trans(int Left,int Up){
 65     For(i,m)
 66       if(code[i]==Up) code[i] = Left;//合并联通快
 67 }
 68  
 69 void dpblank(int i,int j,int cur,int kind){
 70     Rep(k,0,dp[cur].size-1){
 71         decode(dp[cur].st[k]);
 72         int Left = (j==1)?(0):(code[j-1]) ,Up = (i==1)?(0):(code[j]),cnt=0;
 73         if(kind){
 74             int tot = 0;
 75             For(scan,m)  tot+=(code[scan]==Up);
 76             if(tot>1 || !code[j]){
 77                 int tmp = code[j];code[j] = 0;
 78                 dp[nxt].push(encode(),dp[cur].f[k],dp[cur].Loc[k],i,j,0);
 79                 code[j]=tmp;
 80             }
 81         }
 82         if(Left&&Up) trans(Left,Up);else
 83         if(Left||Up) code[j] = Left + Up;
 84         else         code[j] = (5+(cnt++));
 85         dp[nxt].push(encode(),dp[cur].f[k]+kind,dp[cur].Loc[k],i,j,1);
 86     }
 87 }
 88 void DP(){
 89     int cur=0;dp[cur].clear();dp[cur].push(0,0,0,0,0,0);
 90     For(i,n)
 91         For(j,m){
 92             dp[nxt].clear();
 93             dpblank(i,j,cur,maze[i][j]);
 94             cur^=1;
 95         }
 96     Rep(k,0,dp[cur].size-1){
 97         decode(dp[cur].st[k]);
 98         int i;for(i=1;i<=m;i++) if(code[i]>1) break;
 99         if(i<m) continue;
100         if(dp[cur].f[k]<ans){
101             loc = dp[cur].Loc[k];
102             ans=dp[cur].f[k];
103         }
104     }
105     printf("%d\n",ans);
106 }
107  
108 void PrintPath(int i){
109     while(i){
110         pair<pair<int,int>,int> T = opt[i];
111         int x=T.first.first,y=T.first.second,c=T.second;
112         if(!maze[x][y]) Ans[x][y]='x';
113         else if(c==0)   Ans[x][y]='_';
114         else            Ans[x][y]='o';
115         i=pre[i];
116     }
117 }
118  
119 int main(){
120     init();
121     DP();
122     PrintPath(loc);
123     For(i,n)
124       For(j,m)
125         if(j==m) printf("%c\n",Ans[i][j]);
126         else     printf("%c",Ans[i][j]);
127     return 0;
128 }

 

posted @ 2014-08-21 20:44  ZJDx1998  阅读(380)  评论(0编辑  收藏  举报