Zhongshan Jizhong training Day1 test (goof)

T3 painters

Description

Hector is a burly painters, and very like thinking = =

Now, there are N temple pillars arranged in a straight line, from 1 to N label, required by the elders of these pillars will paint fresh coat of paint. Hector tub has K different paint color, the paint can just paint bucket i Ci pillars, and, C1 + C2 + C3 ... CK = N (i.e., N painting pillars just run all the paint). Elders to spite Hector, requires not the same color of the adjacent columns.

Hector like to think not only did not immediately began to paint, but began pondering some strange questions, such as how many paint programs, a total of?

In order to begin to paint as soon as Hector, you tell him the answer as soon as possible.

Input

The first line of a positive integer T, represents a set of test data

For each set of test data:

Line 1: a positive integer K

Line 2: K positive integer, i is the number of columns of the paint bucket can be painted, Ci.

Output
For each set of input data, output line an integer representing the number of programs stucco mod 1000000007.

Sample Input

3

3

1 2 3

5

2 2 2 2 2

10

1 1 2 2 3 3 4 4 5 5

Sample Output

10

39480

85937576

Data Constraint

30% N≤10, T≤5

50% N≤15, T≤5

80% K≤15,Ci≤5,T≤500

100% K≤15,Ci≤6,T≤2000

I thought it was a purely mathematical calculation I looked abandoned.

analysis

We wish to understand the topic from a different angle. We can first stone dyed, then pillars arranged.

We set F [i] [j] denotes the i-color front pillars arranged after all brought, j pillars have their color with that of the left columns are the same.

Filling method is not very good to do, so we consider direct brush table method.

For each state f [i] [j], because the number of each color are known, the current length of the sequence consisting of pillars are known, to sum.

Suppose the number of columns of the i-th color is a [i], then transferred from f [i] to f [i + 1], there will be a [i + 1] th sequence is inserted into the inside of the pillars.

显然,插入时会使原来在一起的两块石柱分开的这种插入会影响到状态本身,所以应该将它单独讨论。

设插入时会插入到p个两边颜色相同的空,q个其他情况的空,那么p+q<=sum+1且p+q<=a[i+1],还剩下a[i+1]-p-q个石柱的插入,它们必然会产生新的颜色相同且相邻的石柱。

那么f[i][j]就可以转移到f[i+1][j-p+a[i+1]-p-q],p与q都可以枚举。将a[i+1]个球放入p+q个空中且不能不放,根据隔板法可知要乘上C(a[i+1]-1,p+q-1).又要在j个两边颜色相同的空中选p个则又要乘上C(j,p),还要在剩下sum+1-j个空中选q个,就还要乘上C(sum+1-j,q)。

直接贴代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#define mod 1000000007
using namespace std;
int C[105][105],f[105][105],T,n,a,sum;
int main()
{
    C[0][0]=1;
    for(int i=1;i<=105;i++)
    {
        C[i][0]=1;
        for(int j=1;j<=i;j++)
        C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
    }
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);sum=0;f[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            for(int j=0;j<=sum+a+1;j++)f[i][j]=0;
            for(int j=0;j<=sum;j++)
            {
                for(int p=0;p<=min(j,a);p++)
                {
                    for(int q=0;q<=min(sum+1-j,a-p);q++)
                    {
                        if(!q&&!p)continue;
                        long long ans=f[i-1][j];int nex=j-p+a-p-q;
                        (ans*=1ll*C[a-1][p+q-1])%=mod;
                        (ans*=1ll*C[j][p])%=mod;
                        (ans*=1ll*C[sum+1-j][q])%=mod;
                        (f[i][nex]+=ans)%=mod;
                    }
                }
            }
            sum+=a;
        }
        printf("%d\n",f[n][0]);
    }
}

 T2 Vani和Cl2捉迷藏

Description

vani和cl2在一片树林里捉迷藏……

这片树林里有N座房子,M条有向道路,组成了一张有向无环图。

树林里的树非常茂密,足以遮挡视线,但是沿着道路望去,却是视野开阔。如果从房子A沿着路走下去能够到达B,那么在A和B里的人是能够相互望见的。

现在cl2要在这N座房子里选择K座作为藏身点,同时vani也专挑cl2作为藏身点的房子进去寻找,为了避免被vani看见,cl2要求这K个藏身点的任意两个之间都没有路径相连。

为了让vani更难找到自己,cl2想知道最多能选出多少个藏身点?

Input

第一行两个整数N,M。

接下来M行每行两个整数x、y,表示一条从x到y的有向道路。

Output

一个整数K,表示最多能选取的藏身点个数。

Sample Input

4 4

1 2

3 2

3 4

4 2

Sample Output

2

Data Constraint

对于20% 的数据,N≤10,M<=20。

对于60% 的数据, N≤100,M<=1000。

对于100% 的数据,N≤200,M<=30000,1<=x,y<=N。

虽然不是很懂但还是应该有的分析

选择一个藏身点后就会有一些路径被废掉不能再选。

然后听说这是求DAG的最小不相交路径覆盖?将原图的点拆成x部与y部,若a能到达b则连Xa指向Yb。

然后DAG的最小路径覆盖=原图的结点数-对应二分图的最大匹配数。(????)

个人理解(乱理解):每一条边代表了原图中的一条路径,每一个匹配代表匹配边两边的点被连在一起,即这条路径上有一个点被选择,整条路径将不再可用。因为求的是最大匹配,所以没有匹配的点在原图中就是一条路径的终点,这些点都可作为藏身点,故答案为原图的结点数-对应二分图的最大匹配数。

代码:

 

#include<cstdio>
#include<cstring>
int n,m,ans,mat[205],vis[205],V[205][205];
int solve(int x)
{
    for(int i=1;i<=n;i++)
    {
        if(V[x][i]&&!vis[i])
        {
            vis[i]=1;
            if(!mat[i]||solve(mat[i]))
            {
                mat[i]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,u,v;i<=m;i++)scanf("%d%d",&u,&v),V[u][v]=1;
    for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
    if(i!=j)V[i][j]=V[i][j]||(V[i][k]&&V[k][j]);
    for(int i=1;i<=n;i++)
    {
        memset(vis,0,sizeof vis);
        ans+=solve(i);
    }
    printf("%d\n",n-ans);
}

 T1 水叮当的舞步

Description

水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变。

为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~

地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色。

水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,地毯左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色。这里连通定义为:两个格子有公共边,并且颜色相同。

由于水叮当是施展轻功来跳舞的,为了不消耗过多的真气,她想知道最少要多少步才能把所有格子的颜色变成一样的。

Input

每个测试点包含多组数据。

每组数据的第一行是一个整数N,表示地摊上的格子有N行N列。

接下来一个N*N的矩阵,矩阵中的每个数都在0~5之间,描述了每个格子的颜色。

N=0代表输入的结束。

Output

对于每组数据,输出一个整数,表示最少步数。

Sample Input

2

0 0

0 0

3

0 1 2

1 1 2

2 2 1

0

Sample Output

0

3

Data Constraint

对于30%的数据,N<=5

对于50%的数据,N<=6

对于70%的数据,N<=7

对于100%的数据,N<=8,每个测试点不多于20组数据。

分析

没看完虹猫蓝兔的我肯定不会做这个题。

观察数据范围,n最大也就8,直接暴力出奇迹,剪枝后复杂度玄学。

先从小到大枚举最大搜索深度(听说这叫迭代加深?),注意不能二分,因为这是指数级别的复杂度增长。

然后进行两个剪枝,一个是变色前统计一下左上角联通块附近有哪几种颜色,变的时候就只用变成这些颜色。

另一个是当 当前深度 加上 剩下联通块的颜色的种类数  大于我们枚举的最大搜索深度时可以直接return 0(听说这跟A*有关?);

写的时候注意局部变量与全局变量,不能混在一起。

代码:

 

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,tmp,I,color[15],ma[15][15],vis[15][15],vised[15][15],used[15];
int cnt1(){int ans=0;for(int i=1;i<=6;i++)ans+=(color[i]>0);return ans;}
void cnt2(int x,int y)
{
    if(ma[x][y]==-1||vised[x][y])return;
    if(ma[x][y]){used[ma[x][y]]=1;return;}vised[x][y]=1;
    cnt2(x+1,y);cnt2(x-1,y);cnt2(x,y+1);cnt2(x,y-1);
}
void print(int x,int y,int c,int dep)
{
    if(ma[x][y]==-1||(ma[x][y]!=c&&ma[x][y]!=0)||vised[x][y])return;vised[x][y]=1;
    if(ma[x][y]==c)ma[x][y]=0,color[c]--,vis[x][y]=dep;
    print(x+1,y,c,dep);print(x-1,y,c,dep);print(x,y+1,c,dep);print(x,y-1,c,dep);
}
bool solve(int noww,int t)
{
    if(noww+cnt1()-1>t)return 0;//这个地方的1减去会多搜索,不减不严谨
    if(1==(color[1]>0)+(color[2]>0)+(color[3]>0)+(color[4]>0)+(color[5]>0)+(color[6]>0))return 1;
    memset(vised,0,sizeof vised);memset(used,0,sizeof used);
    I=noww;cnt2(1,1);int u[15]={0};memcpy(u,used,sizeof u);
    for(int i=1;i<=6;i++)
    {   
        if(!u[i])continue;
        memset(vised,0,sizeof vised);
        print(1,1,i,noww);
        if(solve(noww+1,t))return 1;
        for(int i1=1;i1<=n;i1++)for(int j=1;j<=n;j++){if(vis[i1][j]==noww)color[ma[i1][j]=i]++,vis[i1][j]=-1;}
    }
    return 0;
}
int main()
{
    memset(ma,-1,sizeof ma);
    while(scanf("%d",&n)&&n)
    {
        memset(color,0,sizeof color);
        memset(vis,-1,sizeof vis);
        memset(ma,-1,sizeof ma);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        scanf("%d",&ma[i][j]),color[++ma[i][j]]++;
        for(int i=0;i<=n*n;i++)
        if(solve(0,i)){printf("%d\n",i);break;}
    
    }
}

 

Guess you like

Origin www.cnblogs.com/firecrazy/p/11285601.html