首页 > 代码库 > Topcoder SRM 628 DIV 2

Topcoder SRM 628 DIV 2

被自己蠢哭了。。。。

250-point problem

国际象棋棋盘上给出两个坐标,问象从一个走到另一个最少要几步。

黑格象只能走黑格,白格象只能走白格,只要判断两个坐标的颜色是否相同就能判断是否可达,观察棋盘可以发现坐标的奇偶性决定了格子的颜色;可达的情况下最多两步就能达到,所以只要判断格子是否在同一条斜线上就行了。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<cctype>
#include<cmath>
#include<string>
#include<cstring>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<map>
#include<set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10
#define maxm
#define maxn

using namespace std;

class BishopMove
{
public:
    int howManyMoves(int r1, int c1, int r2, int c2)
    {
        if (r1==r2 && c1==c2)   return 0;
        if (((r1+c1)&1) == ((r2+c2)&1))
        {
            if (abs(r1-r2)==abs(c1-c2)) return 1;

            return 2;
        }


        return -1;
    }
};

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("/home/fcbruce/文档/code/t","r",stdin);
    #endif // ONLINE_JUDGE



    return 0;
}


500-point problem

给出一个括号序列,X可被括号替换,问这串序列是否可能合法。因为当时没看见X的数量不超过5就用了区间DP,有一处下标居然没控制好结果RE。。。。其实可以用DFS求出所有可能的序列,然后用栈判断;区间DP只要求出对这段序列最少加多少括号使其合法就行,如果为0就是合法的,要注意对匹配括号的判断。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<cctype>
#include<cmath>
#include<string>
#include<cstring>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<map>
#include<set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10
#define maxm
#define maxn

using namespace std;

class BracketExpressions
{
public:
    bool check(char x,char y)
    {
        if (x=='(' && y==')' || x=='['&& y==']' ||x=='{' && y=='}')
            return true;

        if (x=='X' && (y==']' || y=='}' || y==')' || y=='X')) return true;

        if (y=='X' && (x=='(' || x=='[' || x=='{')) return true;

        return false;
    }
    string ifPossible(string str)
    {
        int l=str.size();

        int dp[60][60];
        memset(dp,0,sizeof dp);
        for(int i = 0; i<l; i++)
        {
            dp[i][i] = 1;
        }

        for (int m=1;m<l;m++)
        {
            for (int i=0;i<l;i++)
            {
                int j=i+m;
                if (j>=l)   break;
                dp[i][j]=INF;
                if (check(str[i],str[j]))
                    dp[i][j]=min(dp[i][j],dp[i+1][j-1]);
                for (int k=i;k<j;k++)
                {
                    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
                }
            }
        }

        if (dp[0][l-1]==0)  return "possible";
        else
            return "impossible";
    }
};

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("/home/fcbruce/文档/code/t","r",stdin);
    #endif // ONLINE_JUDGE



    return 0;
}


1000-point problem

时间不够,比赛的时候没来得及敲完。。。。。

题意:

给出一个有n个元素的集合E={ x | 0<=x<n , x为整数 },和一段序列f={ xi | 0<=xi,i<n },对于集合E的子集S,有任意i属于S,f[i]=xi 也属于S,问这样的子集有多少个。

分析:

这其实是个图论。

对于每一个i,都对应一个f[i]=xi,如果我取i,那我必定也要取f[i]=xi,即i依赖于f[i]=xi。于是建立有向边i---->f[i]=xi;对于图中的每个强联通分量,这个分量中的所有点一定是同时取的。我们可以进行强联通缩点(tarjan),剩下的DAG中每个点都有取和不取两种关系。应用乘法原理和加法原理,反向建图后通过树形DP求得最后的方案数:对于节点u,取这个节点的方案数是它所有子节点的方案数相乘,不取这个节点的方案数为1。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<cctype>
#include<cmath>
#include<string>
#include<cstring>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<map>
#include<set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10
#define maxm 555555
#define maxn 55

using namespace std;

int fir[maxn];
int u[maxm],v[maxm],nex[maxm];
long long w[maxn];
int n;

int pre[maxn],low[maxn],sccno[maxn];
int st[maxn],top;
int dfs_clock,scc_cnt;

int deg[maxn];

void tarjan_dfs(int _u)
{
    pre[_u]=low[_u]=++dfs_clock;
    st[++top]=_u;
    for (int e=fir[_u];e!=-1;e=nex[e])
    {
        int _v=v[e];
        if (pre[_v]==0)
        {
            tarjan_dfs(_v);
            low[_u]=min(low[_u],low[_v]);
        }
        else
        {
            if (sccno[_v]==0)
                low[_u]=min(low[_u],pre[_v]);
        }
    }

    if (low[_u]==pre[_u])
    {
        scc_cnt++;
        while (true)
        {
            int x=st[top--];
            sccno[x]=scc_cnt;
            if (x==_u)   break;
        }
    }
}

void find_scc()
{
    dfs_clock=scc_cnt=0;
    top=-1;
    memset(sccno,0,sizeof sccno);
    memset(pre,0,sizeof pre);
    for (int i=0;i<n;i++)
    {
        if (pre[i]==0)  tarjan_dfs(i);
    }
}

long long dfs(int _u)
{
    long long temp=1;
    for (int e=fir[_u];~e;e=nex[e])
    {
        temp*=dfs(v[e]);
    }

    return temp+1;
}

class InvariantSets
{
public:
    long long countSets(vector <int> f)
    {
        n=f.size();

        memset(fir,-1,sizeof fir);

        for (int i=0;i<n;i++)
        {
            u[i]=i;v[i]=f[i];
            nex[i]=fir[i];fir[i]=i;
        }

        find_scc();

        memset(fir,-1,sizeof fir);
        memset(deg,0,sizeof deg);

        int e=0;

        for (int i=0;i<n;i++)
        {
            if (sccno[u[i]]==sccno[v[i]])   continue;

            u[e]=sccno[u[i]];v[e]=sccno[v[i]];

            swap(u[e],v[e]);

            nex[e]=fir[u[e]];
            deg[v[e]]++;
            fir[u[e]]=e++;
        }

        for (int i=1;i<=scc_cnt;i++)
        {
            if (deg[i]==0)
            {
                u[e]=i;v[e]=0;
                swap(u[e],v[e]);
                nex[e]=fir[u[e]];
                fir[u[e]]=e++;
            }
        }

        return dfs(0)-1;



    }
};

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("/home/fcbruce/文档/code/t","r",stdin);
    #endif // ONLINE_JUDGE

    InvariantSets a;
    itn x,y;
    while (~scanf("%d",&x))
    {
        vector <int>    v;
        for (int i=0;i<x;i++)
        {
            scanf("%d",&y);
            v.push_back(y);
        }

        printf("%lld\n",a.countSets(v));
    }


    return 0;
}


Topcoder SRM 628 DIV 2