[NOI2011]

来自FallDream的博客,未经允许,请勿转载,谢谢。


省选完挂。但是善良的教练今天丢了一套NOI2011给我们训练 6道题233(虽然一道题做过了,一道题普及组的都会,就算是4道吧)

熬了一天,总算啃掉了四题中的三题 D2T3那个牛逼的博弈论实在不知道怎么做,只好去看看题解233

简单讲一下题解..

D1T1兔农

农夫栋栋近年收入不景气,正在他发愁如何能多赚点钱时,他听到隔壁的小朋友在讨论兔子繁殖的问题。

问题是这样的:第一个月初有一对刚出生的小兔子,经过两个月长大后,这对兔子从第三个月开始,每个月初生一对小兔子。新出生的小兔子生长两个月后又能每个月生出一对小兔子。问第n个月有多少只兔子?

聪明的你可能已经发现,第n个月的兔子数正好是第n个Fibonacci(斐波那契)数。栋栋不懂什么是Fibonacci数,但他也发现了规律:第i+2个月的兔子数等于第i个月的兔子数加上第i+1个月的兔子数。前几个月的兔子数依次为:

1 1 2 3 5 8 13 21 34 …

栋栋发现越到后面兔子数增长的越快,期待养兔子一定能赚大钱,于是栋栋在第一个月初买了一对小兔子开始饲养。

每天,栋栋都要给兔子们喂食,兔子们吃食时非常特别,总是每k对兔子围成一圈,最后剩下的不足k对的围成一圈,由于兔子特别害怕孤独,从第三个月开始,如果吃食时围成某一个圈的只有一对兔子,这对兔子就会很快死掉。

我们假设死去的总是刚出生的兔子,那么每个月的兔子数仍然是可以计算的。例如,当k=7时,前几个月的兔子数依次为:

1 1 2 3 5 7 12 19 31 49 80 …

给定n,你能帮助栋栋计算第n个月他有多少对兔子么?由于答案可能非常大,你只需要告诉栋栋第n个月的兔子对数除p的余数即可。

1s/256MB   n<=10^18 k<=10^6 p<=10^9

 

上来就刚这道题 但是不会.. 仔细想想没有那么复杂

在一个点从1变成0之后,假设这个1之前的数字是x,之后的序列就变成了x,x,2x,3x,恰好是一个斐波那契数列!

这种斐波那契数列不同的显然不超过k个,之后就会出现循环节。推到这里,解法就比较显然了。

先暴力求出斐波那契数列膜k意义下的每个数值最小的出现位置,然后找到第一个1。

之后我们不断拿出1之前的数字,用exgcd求它下一次变成1的时候,也就是它关于k的逆元,那么它下次出现1的位置就是这个逆元在斐波那契数列的第一次的出现位置。

我们对一个数求解的时候给它打一个标记,一旦我们找到了已经求解过的数,说明找到了循环节。

但是我们还要支持-1操作,所以考虑给斐波那契矩阵加一维1.  

$\begin{equation}
\left[
\begin{matrix}
fi\\
f_{i-1}\\
1
\end{matrix}
\right]
\end{equation}$*$\begin{equation}
\left[
\begin{matrix}
1&1&0\\
1&0&0\\
0&0&1&
\end{matrix}
\right]
\end{equation}$=$\begin{equation}
\left[
\begin{matrix}
f_{i+1}\\
fi\\
1
\end{matrix}
\right]
\end{equation}$

$\begin{equation}
\left[
\begin{matrix}
fi\\
f_{i-1}\\
1
\end{matrix}
\right]
\end{equation}$*$\begin{equation}
\left[
\begin{matrix}
1&0&-1\\
0&1&0\\
0&0&1&
\end{matrix}
\right]
\end{equation}$=$\begin{equation}
\left[
\begin{matrix}
fi-1\\
f_{i-1}\\
1
\end{matrix}
\right]
\end{equation}$

用这两个矩阵就可以求出循环节的转移矩阵,然后直接快速幂就行啦。

一开始没想到要加一维 后来乱改 应该是我写的最丑的代码之一..

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#define ll long long
#define MN 2000000
using namespace std;
inline ll read()
{
    ll x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}
ll n;
int K,p,f[MN+5],mp[1000005];
ll L[1000005];
bool flag=0;

struct Matrix 
{
    int s[4][4];
    Matrix(){memset(s,0,sizeof(s));}
}A,B,C,D,Mem[1000005];

Matrix Mul(Matrix a,Matrix b,int mod)
{
    Matrix c;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
            for(int k=1;k<=3;k++)
                c.s[i][j]=(c.s[i][j]+1LL*a.s[i][k]*b.s[k][j])%mod;
    return c;    
}

void Init()
{
    memset(C.s,0,sizeof(C.s));
    C.s[1][1]=C.s[1][2]=C.s[2][1]=1;
    C.s[2][2]=0;C.s[3][3]=1;
}

Matrix MatPow(Matrix C,Matrix D,ll k,int mod)
{
    for(;k;k>>=1,D=Mul(D,D,mod))
        if(k&1) C=Mul(C,D,mod);
    return C;
}

void vio(Matrix&D,ll k,int mod)
{
    Init();
    for(;k;k>>=1,C=Mul(C,C,mod))
        if(k&1) D=Mul(C,D,mod);
}

inline ll exgcd(ll a,ll b,ll&x,ll&y)
{
    if(!b){x=1;y=0;return a;}
    ll c=exgcd(b,a%b,x,y);
    ll t=x;x=y;y=t-a/b*x;
    return c;    
}

ll getinv(int x,int mod)
{
    ll X,Y;
    if(1!=exgcd(x,mod,X,Y)) return 0; 
    return (X%mod+mod)%mod;
}

inline void Dec(Matrix&D)
{
    memset(A.s,0,sizeof(A.s));
    A.s[1][1]=A.s[2][2]=A.s[3][3]=1;A.s[1][3]=p-1;  
    D=Mul(A,D,p);
    B.s[1][1]=0;
}

Matrix GetSq(int x)
{
    Matrix E;int y=x;
    E.s[1][1]=E.s[2][2]=E.s[3][3]=1;
    do 
    {
        ll z=getinv(y,K);z=mp[z];
        vio(E,z,p);vio(B,z,K);Dec(E);
        y=B.s[2][1];
    }while(y!=x);
    return E;
}

void Solve(int x)
{
    if(!n) return;
    if(L[x]) {ll tms=n/(L[x]-n);
                if(tms)
                {
                    Matrix T=GetSq(x);
                    T=MatPow(T,T,tms-1,p);
                    D=MatPow(T,D,1,p);
                }n%=(L[x]-n);
                flag=true;return;}
    L[x]=n;Mem[x]=D;ll y;
    if(!(y=getinv(x,K))) return;
    y=mp[y];if(y>n) return;
    n-=y;
    vio(D,y,p);vio(B,y,K);
//    B.print();
    Dec(D);Solve(B.s[2][1]);
}

int main()
{
    f[1]=f[2]=1;B.s[1][1]=B.s[2][1]=D.s[1][1]=D.s[2][1]=B.s[3][1]=D.s[3][1]=1;
    n=read();K=read();p=read();
    for(int i=3;i<=MN;i++) f[i]=(f[i-1]+f[i-2])%K;
    for(int i=3;i<=MN;i++) if(!mp[f[i]]) mp[f[i]]=i;
    if(!mp[1]||mp[1]>n) return vio(D,max(0LL,n-2),p),0*printf("%d\n",D.s[1][1]); 
    vio(D,mp[1]-2,p);vio(B,mp[1]-2,K);n-=mp[1];Dec(D);
    Solve(B.s[2][1]);
    if(flag) 
    {
        memset(L,0,sizeof(L));
        Solve(B.s[2][1]);    
    } 
    vio(D,n,p);printf("%d\n",D.s[1][1]);
    return 0;
}

D1T2 智能车比赛

新一届智能车大赛在JL大学开始啦!比赛赛道可以看作是由n个矩形区域拼接而成(如下图所示),每个矩形的边都平行于坐标轴,第i个矩形区域的左下角和右上角坐标分别为(xi,1,yi,1)和(xi,2,yi,2)。

题目保证:xi,1<xi,2=xi+1,1,且yi,1< yi,2,相邻两个矩形一定有重叠在一起的边(如图中虚线所示),智能车可以通过这部分穿梭于矩形区域之间。

给定速度(意义不明)求起点到终点的最短时间。

1s/256MB n<=2000

 

发现到达的点一定是矩形的点,然后直接n^2dp就行了  计算几何比较烦

但是我菜,写了建图最短路,差点T了,大家还是学学dp做法吧,比我的优很多...

代码蛮贴一贴

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#define pa pair<double,int> 
#define mp(x,y) make_pair(x,y)
#define MN 8005
#define FROM 8002
#define TO 8001
#define eps 1e-7
#define INF 2000000000
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}
inline double sqr(double x){return x*x;}
struct P
{
    double x,y;    
    P(double _x=0,double _y=0):x(_x),y(_y){}
    double operator^(const P&b){return x*b.y-y*b.x;}
    P operator-(const P&b){return P(x-b.x,y-b.y);}
    friend double dis(P a,P b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));} 
}S,T;
int U[MN+5],D[MN+5],X[MN+5];
struct L
{    
    P p,v;
    L(){}
    L(P a,P b):p(a),v(b){}
    bool Left(P x){return (v^(x-p))>-eps;}
    bool Right(P x){return (v^(x-p))<eps;}
};
struct edge{int to,next;double f;}e[MN*100+5];
double v,d[MN+5];
int n,cnt=0,head[MN+5];
priority_queue<pa,vector<pa>,greater<pa> >q;
inline void ins(int f,int t,double w)
{
//    cout<<"ins"<<f<<" "<<t<<" "<<w<<endl;
    e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
    e[++cnt]=(edge){f,head[t],w};head[t]=cnt;
}

void SolveLeft(int R,int from,P x)
{
    L up(x,P(0,INF)),down(x,P(0,-INF));
    for(register int i=R;~i;--i)
    {
        P u=P(X[i],U[i]),d=P(X[i],D[i]); 
        if(up.Left(u)&&down.Right(u))
            ins(from,n+1+i,dis(u,x));
        if(up.Left(d)&&down.Right(d))
            ins(from,i,dis(d,x));
        if(up.Left(u)) up=L(x,u-x);
        if(down.Right(d)) down=L(x,d-x);
    }
}

void SolveRight(int Le,int from,P x)
{
    L up(x,P(0,INF)),down(x,P(0,-INF));
    for(register int i=Le;i<=n;++i)
    {
        P u=P(X[i],U[i]),d=P(X[i],D[i]); 
        if(up.Right(u)&&down.Left(u))
            ins(from,n+1+i,dis(u,x));
        if(up.Right(d)&&down.Left(d))
            ins(from,i,dis(d,x));
        if(up.Right(u)) up=L(x,u-x);
        if(down.Left(d)) down=L(x,d-x);
    }
}

void dij()
{
    memset(d,127,sizeof(d));d[FROM]=0;
    q.push(mp(0,FROM));
    while(!q.empty())
    {
        while(!q.empty()&&q.top().first!=d[q.top().second]) q.pop();
        if(q.empty()) break;
        int x=q.top().second;q.pop();
        for(int i=head[x];i;i=e[i].next)
            if(e[i].f+d[x]<d[e[i].to])
            {
                d[e[i].to]=d[x]+e[i].f;
                q.push(mp(d[e[i].to],e[i].to));    
            }
    }
}

int main()
{
    n=read();
    U[0]=INF;D[0]=-INF;
    for(register int i=1;i<=n;i++)
    {
        int x1=read(),y1=read(),x2=read(),y2=read();
        X[i-1]=x1;X[i]=x2;
        U[i-1]=min(U[i-1],y2);
        D[i-1]=max(D[i-1],y1);
        U[i]=y2;D[i]=y1;
    }
    S.x=read();S.y=read();T.x=read();T.y=read();
    for(register int i=0;i<=n;i++)
    {
        if(i) SolveLeft(i-1,n+1+i,P(X[i],U[i])),
              SolveLeft(i-1,i,P(X[i],D[i]));    
        if(i<n) SolveRight(i+1,n+1+i,P(X[i],U[i])),
                SolveRight(i+1,i,P(X[i],D[i]));
    }
    register int i=0,j=0;bool flag=1;
    for(;X[i]<S.x;++i);    
    for(;X[j]<T.x;++j);
    flag&=(i==j);
    if(X[i]==S.x)
    { 
        ins(i,FROM,dis(P(X[i],D[i]),S)),ins(i+n+1,FROM,dis(S,P(X[i],U[i])));
        if(S.y>=D[i]&&S.y<=U[i]&&i>0) 
            if(i>0)SolveLeft(i-1,FROM,S);
    }
    else if(i>0)SolveLeft(i-1,FROM,S);
    for(;X[i]==S.x;++i);if(i<n)SolveRight(i,FROM,S);
    if(X[j]==T.x) 
    {
        ins(j,TO,dis(T,P(X[j],D[j]))),ins(j+n+1,TO,dis(T,P(X[j],U[j])));
        if(T.y>=D[j]&&T.y<=U[j]&&j>0) 
            if(j>0)SolveLeft(j-1,TO,T);
    }
    else if(j>0)SolveLeft(j-1,TO,T);
    for(;X[j]==T.x;++j);if(j<n)SolveRight(j,TO,T);
    dij();double v;scanf("%lf",&v);    
    if(i==j&&flag) d[TO]=min(d[TO],dis(S,T));
    printf("%.10lf\n",d[TO]/v);
    return 0;
}

D1T3阿狸的打字机 

以前做的题目 戳这里

D2T1道路修建

在 W 星球上有 n 个国家。为了各自国家的经济发展,他们决定在各个国家 之间建设双向道路使得国家之间连通。但是每个国家的国王都很吝啬,他们只愿 意修建恰好 n – 1 条双向道路。 每条道路的修建都要付出一定的费用,这个费用等于道路长度乘以道路两端 的国家个数之差的绝对值。例如,在下图中,虚线所示道路两端分别有 2 个、4 个国家,如果该道路长度为 1,则费用为 1×|2 – 4|=2。图中圆圈里的数字表示国 家的编号。

由于国家的数量十分庞大,道路的建造方案有很多种,同时每种方案的修建 费用难以用人工计算,国王们决定找人设计一个软件,对于给定的建造方案,计 算出所需要的费用。请你帮助国王们设计一个这样的软件。

n<=1000000  1s/256MB

普及组水平的题目...

#include<iostream>
#include<cstdio>
#define MN 1000000
#define ll long long
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}
 
int n,head[MN+5],cnt=0,size[MN+5];
struct edge{int to,next,w;}e[MN*2+5];
ll ans=0;
inline void ins(int f,int t,int w){e[++cnt]=(edge){t,head[f],w};head[f]=cnt;}
inline int abs(int x){return x<0?-x:x;}
void dfs(int x,int f)
{
    size[x]=1;
    for(int i=head[x];i;i=e[i].next)
        if(e[i].to!=f)
        {
            dfs(e[i].to,x);
            size[x]+=size[e[i].to];
            ans+=1LL*e[i].w*abs(size[e[i].to]-(n-size[e[i].to]));
        }
}
 
int main()
{
    n=read();
    for(int i=1;i<n;i++) 
    {
        int x=read(),y=read(),w=read();
        ins(x,y,w);ins(y,x,w);
    }
    dfs(1,0);
    printf("%lld\n",ans);
    return 0;
}

D2T2 Noi嘉年华

NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办。每个嘉年华可能包含很多个活动,而每个活动只能在一个嘉年华中举办。

现在嘉年华活动的组织者小安一共收到了 n个活动的举办申请,其中第 i 个活动的起始时间为 Si,活动的持续时间为Ti。这些活动都可以安排到任意一个嘉年华的会场,也可以不安排。

小安通过广泛的调查发现,如果某个时刻,两个嘉年华会场同时有活动在进行(不包括活动的开始瞬间和结束瞬间),那么有的选手就会纠结于到底去哪个会场,从而变得不开心。所以,为了避免这样不开心的事情发生,小安要求不能有两个活动在两个会场同时进行(同一会场内的活动可以任意进行)。

另外,可以想象,如果某一个嘉年华会场的活动太少,那么这个嘉年华的吸引力就会不足,容易导致场面冷清。所以小安希望通过合理的安排,使得活动相对较少的嘉年华的活动数量最大。

此外,有一些活动非常有意义,小安希望能举办,他希望知道,如果第i 个活动必须举办(可以安排在两场嘉年华中的任何一个),活动相对较少的嘉年华的活动数量的最大值。

n<=200  1s/256MB

这道题看起来很可做  但是啃了很久做不出来  还好yy出了一个比较靠谱的dp方程,总算过了  差点忍不住去看题解了233

离散时间点,然后f[i][j]表示前i个时间点其中一个嘉年华举办j场活动,另一场最多举办几场,转移比较显然。 g[i][j]表示后.....

令h[i][j]表示时间点i到j的区间最多能办几场活动,那么对于每一个时间段x-y,答案是Ans[x][y]=max(min(f[x-1][i]+h[x][y]+g[y+1][k-i],k)) 后面那一串显然可以二分。

所以处理完Ans数组之后,每个询问只要去查一个最大值就行了。复杂度n^3logn

貌似可以借助单调性做到n^3   但是莫名没有我跑的快...

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define MN 400
#define INF 1000000000 
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

int f[MN+5][MN+5],g[MN+5][MN+5],h[MN+5][MN+5],p[MN+5],Ans[MN+5][MN+5],tot=0,n,m=1;
struct eve{int b,e;}e[MN+5];

int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        e[i].b=read();
        e[i].e=e[i].b+read()-1;    
        p[++tot]=e[i].b;
        p[++tot]=e[i].e;
    }
    sort(p+1,p+tot+1);
    for(int i=2;i<=tot;i++)
        if(p[i]!=p[i-1]) p[++m]=p[i];
    for(int i=1;i<=n;i++)
    {
        e[i].b=lower_bound(p+1,p+m+1,e[i].b)-p;
        e[i].e=lower_bound(p+1,p+m+1,e[i].e)-p;
        h[e[i].b][e[i].e]++;
    } 
    for(int len=2;len<=m;len++)
        for(int i=1;i+len-1<=m;i++)
        {
            int j=i+len-1;
            h[i][j]=h[i][j]+h[i+1][j]+h[i][j-1]-h[i+1][j-1]; 
        }
    for(int i=0;i<=m+1;i++)
        for(int j=0;j<=n;j++) f[i][j]=g[i][j]=-INF;
    f[0][0]=g[m+1][0]=0;
    for(int i=1;i<=m;i++)
        for(int k=0;k<=n;k++)
        {
            for(int j=0;j<i;j++)
                if(h[j+1][i]<=k)
                    f[i][k]=max(f[i][k],f[j][k-h[j+1][i]]);
            f[i][k]=max(f[i][k],f[i-1][k]);
            if(f[i][k]>=0) f[i][f[i][k]]=max(f[i][f[i][k]],k);
        }
    for(int i=m;i;--i)
        for(int k=0;k<=n;k++)
        {
            for(int j=i+1;j<=m+1;j++)
                if(h[i][j-1]<=k)
                    g[i][k]=max(g[i][k],g[j][k-h[i][j-1]]);
            g[i][k]=max(g[i][k],g[i+1][k]);
            if(g[i][k]>=0) g[i][g[i][k]]=max(k,g[i][g[i][k]]);
        }            
    int ans=0;
    for(int i=1;i<=n;i++)
        ans=max(ans,min(i,f[m][i]));
    printf("%d\n",ans);
    for(int i=0;i<=m;i++)
        for(int j=i+1;j<=m+1;j++)
        {
            int l=1,r=n,ans=0,mid;
            while(l<=r)
            {
                mid=l+r>>1;bool flag=false;
                for(int k=0;k<=mid;k++)
                    if(f[i][k]+g[j][mid-k]+h[i+1][j-1]>=mid)
                    {
                        flag=true;
                        break;
                    }
                if(flag) ans=mid,l=mid+1;
                else r=mid-1;
            }
            Ans[i][j]=ans;
        }
    for(int i=1;i<=n;i++)
    {
        int ans=0;
        for(int j=0;j<e[i].b;j++)
            for(int k=e[i].e+1;k<=m+1;k++)
                ans=max(ans,Ans[j][k]);    
        printf("%d\n",ans);
    }
    return 0;
}

D2T3

这些天,兔兔和蛋蛋喜欢上了一种新的棋类游戏。 这个游戏是在一个n行m列的棋盘上进行的。游戏开始之前,棋盘上有一个格子是空的,其它的格子中都放置了一枚棋子,棋子或者是黑色,或者是白色。 每一局游戏总是兔兔先操作,之后双方轮流操作,具体操作为:

兔兔每次操作时,选择一枚与空格相邻的白色棋子,将它移进空格。

蛋蛋每次操作时,选择一枚与空格相邻的黑色棋子,将它移进空格。

第一个不能按照规则操作的人输掉游戏。为了描述方便,下面将操作“将第x行第y列中的棋子移进空格中”记为M(x,y)。 例如下面是三个游戏的例子。

最近兔兔总是输掉游戏,而且蛋蛋格外嚣张,于是兔兔想请她的好朋友——你——来帮助她。她带来了一局输给蛋蛋的游戏的实录,请你指出这一局游戏中所有她“犯错误”的地方。 注意:

两个格子相邻当且仅当它们有一条公共边。

兔兔的操作是“犯错误”的,当且仅当,在这次操作前兔兔有必胜策略,而这次操作后蛋蛋有必胜策略。

 

丢个链接:这里有很详细的题解 

#include<cstdio>
#include<iostream>
#define MN 1600
#define MC 40
using namespace std;
inline int read()
{
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x;
}
int n,m,head[MN+5],cnt=0,match[MN+5],mark[MN+5],fx,fy,s[MC+5][MC+5],tot=0,cn=0,Ans[MN+5];
struct edge{int to,next;}e[MN*4+5];
char st[MC+5][MC+5];
bool ban[MN+5];
const int dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
inline void ins(int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;}
inline int num(int x,int y){return (x-1)*m+y;}

bool Dfs(int x)
{
    for(int i=head[x];i;i=e[i].next)
        if(mark[e[i].to]!=tot&&!ban[e[i].to])
        {
            mark[e[i].to]=tot;
            if(!match[e[i].to]||Dfs(match[e[i].to]))
            {
                match[x]=e[i].to;
                match[e[i].to]=x;
                return true;
            }
        }
    return false;
}

int calc(int x)
{
    ban[x]=1;
    if(!match[x])return 0;
    int rt=match[x];
    match[rt]=match[x]=0;
    return ++tot,!Dfs(rt);
}

int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++) scanf("%s",st[i]+1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(st[i][j]=='.') fx=i,fy=j;
            else s[i][j]=st[i][j]=='X'?0:1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=0;k<4;k++)
            {
                int x=i+dis[k][0],y=j+dis[k][1];
                if(x<1||y<1||x>n||y>m||s[i][j]==s[x][y]) continue;
                ins(num(i,j),num(x,y));
            }
    for(int i=1;i<=n*m;++i) if(!match[i])++tot,Dfs(i);
    int q=read();
    for(int i=1;i<=q;++i)
    {
        int res1=calc(num(fx,fy));
        fx=read(),fy=read();
        int res2=calc(num(fx,fy));
        if(res1&&res2) Ans[++cn]=i;
        fx=read();fy=read();
    }
    cout<<cn<<endl;
    for(int i=1;i<=cn;i++)printf("%d\n",Ans[i]);
    return 0;
}

 

posted @ 2017-04-25 23:02  FallDream  阅读(538)  评论(0编辑  收藏  举报