uva 1444 Knowledge for the masses

uva 1444

Description

 

You are in a library equipped with bookracks that move on rails. There are many parallel rails, i.e., the bookracks are organized in several rows, see figure:

 

\epsfbox{p4629a.eps}

 

The boockracks in the library. There is no passage to the librarian at the moment.

To borrow a book, you have to find the librarian, who seems to hide on the opposite side of the bookracks. Your task then is to move the racks along the rails so that a passage forms. Each rack has a certain integer width, and can be safely positioned at any integer point along the rail. (A rack does not block in a non-integer position and could accidentally move in either direction). The racks in a single row need not be contiguous -- there can be arbitrary (though integer) space between two successive bookracks. A passage is formed at position k if there is no bookrack in the interval (kk + 1) in any row (somehow you don't like the idea of trying to find a more sophisticated passage in this maze.)

 

\epsfbox{p4629b.eps}

 

The passages formed in the library: at position 8 (the left figure) and at position 9 (the right figure). Both attained at cost 3 by moving the bookracks marked with arrows.

Moving a rack requires a certain amount of efflort on your part: moving it in either direction costs 1. This cost does not depend on the distance of the shift, which can be explained by a well known fact that static friction is considerably higher than kinetic friction. Still, you are here to borrow a book, not to work out, so you would like to form a passage (at any position) with as little efflort as possible.

 

Input 

The input contains several test cases. The first line of the input contains a positive integer Z$ \le$15, denoting the number of test cases. ThenZ test cases follow, each conforming to the format described below.

 


Two space separated integers R and L(1$ \le$R, 1$ \le$L$ \le$106) are given in the first line of an input instance. They denote the number of rows and the width of each and every row, respectively. Then R lines with rows descriptions follow. Each such line starts with an integer ni, followed by ni integers ai, 1ai, 2,...ai, ni, all separated by single spaces. Number ai, j denotes either the width of a bookrack when ai, j > 0or a unit of empty space when ai, j = 0. Note that for any row i,$ \sum_{{j}}^{}$ai, j equals L minus the number of ai, j that are equal to zero. You may assume that n1 + n2 + ... nR$ \le$2*107. Moreover, there will be at least one 0 in the description of each row, which means that creating a passage is always possible.

 

Output 

For each test case, your program has to write an output conforming to the format described below.

 


In the first line, your program should output the minimum cost of making a passage through the bookracks. In the second line, it should print out the increasing sequence of all the positions at which a minimum cost passage can be formed.

 

Sample Input 

 

1 
4 10 
8 1 2 1 0 1 2 0 1
7 2 2 2 1 0 1 0 
6 1 3 2 0 2 1 
7 2 1 2 0 2 1 0

 

Sample Output 

 

3 
8 9

题意:从上面到下面需要通过很多行,每一行都有书架或者空格,只有空格才能通过,问你最少需要移动多少书架才能达到终点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e6+10;
int g[maxn],can[maxn],zero[maxn],pos[maxn],a[maxn],cost[maxn];
int N,H;
void Init()
{
   int n;
   cin>>n;
   for(int i=0;i<n;i++) cin>>a[i];
   fill(cost,cost+maxn,-1);
   int ze=0,now=0;
   for(int i=0;i<n;i++)
   {
       if(a[i]==0)
       {
           zero[ze++]=i;
           can[now++]++;
       }
       else
       {
           now+=a[i];
           int k=min(ze,a[i]);//空格长度与待移动书架长度,最多也只能移动空格位那么长
           for(int j=1;j<=k;j++)
           {
               cost[now-j]=i-zero[ze-j]-(j-1);//只移j个,计算给(now-j)腾出空位需付代价
               g[now-j]+=cost[now-j];//cost只是这一行的代价,总计用g(i)
               can[now-j]++;//那么(now-j) 这个位置也可以通行了
           }
       }
   }
   reverse(a,a+n);   //开始从右往左移
   now--;ze=0;        //ze赋值为零!!!!!代表现在还没有看到可以直接通过的位置
   for(int i=0;i<n;i++)
   {
       if(a[i]==0)
       {
           zero[ze++]=i;
           now--;
       }
       else
       {
           now-=a[i];
           int c=min(a[i],ze);
           for(int j=1;j<=c;j++)
           {
               if(cost[now+j]==-1)
               {
                   cost[now+j]=i-zero[ze-j]-(j-1);
                   g[now+j]+=cost[now+j];
                   can[now+j]++;
               }
               else
               {
                   int cc=i-zero[ze-j]-(j-1);
                   g[now+j]+=min(0,cc-zero[now+j]);
               }
           }
       }
   }
}

void Print()       //只要满足最小移动数的列举,其余就算可以通过也不要
{
    int ans=1e9;
    int cnt=0;
    for(int i=0;i<H;i++)
    {
        if(can[i]==N)
        {
            if(ans>g[i])
            {
                ans=g[i];
                cnt=0;
                pos[cnt++]=i;
            }
            else if(ans==g[i])
            pos[cnt++]=i;
        }
    }
    cout<<ans<<endl;
    for(int i=0;i<cnt;i++) cout<<pos[i]<<" ";
    puts("");
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
     memset(can,0,sizeof(can));   //一定要清零
     memset(cost,0,sizeof(cost));
     memset(pos,0,sizeof(pos));
     memset(g,0,sizeof(g));       //一定要清零
     cin>>N>>H;
     for(int i=0;i<N;i++) Init();
     Print();
    }
    return 0;
}
View Code

 

posted @ 2015-10-27 18:16  江南何采莲  阅读(232)  评论(0编辑  收藏  举报