SRM 575 DIV2 博弈P/N分析 + 最大流

250pt:

题意:

给出一个序列,该序列中可能有相同的值,然后交换任意两个数形成不同序列的数量。

思路:
由于这里的序列长度为n,n <= 1000 所以我们只要利用set的蛆虫特性,O(n^2)枚举swap就可以了。但是如果n非常大达到10^7怎么办?其实我们还可以利用set来记录该序列中一共出现了多少不同的数,只要出现一对不同的数那么交换这两个肯定能够得到一个不同的序列最后结果就是(set.size() - 1)*set.size()/2; 

View Code
#define M 5007 
#define N 1007 
using namespace std; 


int n,m; 
class TheSwapsDivTwo 
{ 
        public: 

        set<vector<int> > st; 
        int find(vector <int> sequence) 
        { 
            int i,j; 
            st.clear(); 
            int sz = sequence.size(); 
            for (i = 0; i < sz; ++i) 
            { 
                for (j = 0; j < sz; ++j) 
                { 
                    if (i == j) continue; 
                    swap(sequence[i],sequence[j]); 
                    st.insert(sequence); 
                    swap(sequence[i],sequence[j]); 
                } 
            } 
            return st.size(); 
        } 


}; 

 

500pt:

题意:

两个人玩游戏,给定一个数,我们减去他的因子(除了1和他本身外)得到一个新数,两个人轮流玩游戏.最后谁无数可减即为失败。

思路:

典型的P\N分析找规律,不过这题目给的n范围很小,我们只需要按照打表找规律的方法就能过。首先质数肯定是必败点,而对于非质数我们只要枚举他的因子,然后根据必败点,必胜点的定义来解决即可。 其实这里打标之后的规律是偶数(除了2,2*4,2*4*4.....)都是必胜点,技术都是必败点

View Code
#define M 5007 
#define N 1007 
using namespace std; 


int n,m; 
class TheNumberGameDivTwo 
{ 
        public: 
        int f[N]; 
        int prim[N]; 
        void PR() 
        { 
            int i,j; 
            CL(prim,0); 
            prim[1] = prim[0] = 1; 

            for (i = 2; i*i < N; ++i) 
            { 
                if (!prim[i]) 
                { 
                    for (j = 2*i; j < N; j += i) 
                    { 
                        prim[j] = 1; 
                    } 
                } 
            } 
        } 
        void init() 
        { 
            int i,j; 
            CL(f,0); 
            f[4] = f[6] = 1; 
            for (i = 7; i < N; ++i) 
            { 
                if (!prim[i]) f[i] = 0; 
                else 
                { 
                    for (j = 2; j < i; ++j) 
                    { 
                        if (i%j == 0) 
                        { 
                            if (f[i - j] == 0) 
                            { 
                                f[i] = 1; 
                                break; 
                            } 
                        } 
                    } 
                } 
            } 
        } 
        string find(int n) 
        { 
            PR(); 
            init(); 
            if (f[n] == 0)return "Brus"; 
            else return "John"; 
        } 


}; 

 

1000pt:

题意:

给你一个n*m的矩形,矩形由‘X’与'.'组成用一个

00

0

该形状的'L'去覆盖,该形状可以任意旋转i*90度之后使用。‘X’表示不能覆盖,‘.’表示可以覆盖, (i + j)%2 == 0的方格是黑色的。我们要求求用最多的'L'覆盖该该矩形,并且保证每个'L'的拐角处覆盖的是黑色。

思路:

最大流。

这题目真心想不出来。看了别人的代码,DP但是没有看懂,后来看了一个贪心的做法:就是枚举出所有可以覆盖的状态,然后求每个状态与之相交的其他状态的个数,然后贪心按个数从小到大排序。覆盖,标记已覆盖的最后求结果即可。但是我按照该思路写了之后老是不对。估计又加数据了。本来这种贪心就不应该对。

DP:没看懂。

最大流:话说这题目最大流真心不好想。

我们观察可以发现,题目的黑色的点分布是又规律的。我们枚举所有不是黑色的点,偶数行做由源点发出来的点,奇数行做发向汇点的点,(其实换过来这里都一样)。然后满足将黑色的点差点赋权值为1这样就保证了每一个黑色点只能存在于一个‘L'的拐角处了。 关键还是建图然后套最大流模板即可。

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll long long
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define M 272488
#define N 522
using namespace std;


const int inf = 0x7fffffff;

int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};


int level[N],q[M];

struct node{
    int v,w,u;
    int next;
}g[M + 10];

int head[N],ct,out[N];

void add(int u,int v,int w){
    g[ct].v = v;
    g[ct].w = w;
    g[ct].next = head[u];
    head[u] = ct++;

    g[ct].v = u;
    g[ct].w = 0;
    g[ct].next = head[v];
    head[v] = ct++;
}
bool layer(int s,int e){
    int i;
    CL(level,-1);
    level[s] = 0;
    int l = 0, r= 0;
    q[r] = s;
    while (l <= r){
        int u = q[l++];
        for (i = head[u]; i != -1; i = g[i].next){
            int v = g[i].v;
            if (level[v] == -1 && g[i].w > 0){
                level[v] = level[u] + 1;
                q[++r] = v;
                if (v == e) return true;
            }
        }
    }
    return false;
}
int find(int s,int e){
    int top = 1,i;
    int ans = 0;
    while (top){
        int u = (top == 1 ? s : g[q[top - 1]].v);
        if (u == e){
            int MIN = inf ,pos;
            for (i = 1; i < top; ++i){
                int tp = q[i];
                if (g[tp].w < MIN){
                    MIN = g[tp].w;
                    pos = i;
                }
            }
            for (i = 1; i < top; ++i){
                int tp = q[i];
                g[tp].w -= MIN;
                g[tp^1].w += MIN;
            }
            ans += MIN;
            top = pos - 1;
        }
        else{
            for (i = head[u]; i != -1; i = g[i].next){
                int v = g[i].v;
                if (level[v] == level[u] + 1 && g[i].w > 0){
                    q[top++] = i;
                    break;
                }
            }
            if (i == -1){
                top--;
                level[u] = -1;
            }
        }
    }
    return ans;
}
int dinic(int s,int e){
    int ans = 0;
    while (layer(s,e))  ans += find(s,e);
    return ans;
}

class TheTilesDivTwo
{
        public:
        int n,m;
        int idx(int i,int j,char a)
        {
            int as = i*m + j;
            return a? as: as + n*m;
        }

        int find(vector <string> bd)
        {
            int i,j,k;
            n = bd.size();
            m = bd[0].size();
            CL(head,-1); ct = 0;
            if (n < 2) return 0;
            if (m < 2) return 0;
            int s = 2*n*m,e = 2*n*m + 1;

            for (i = 0; i < n; ++i)
            {
                for (j = 0; j < m; ++j)
                {
                    add(idx(i,j,1),idx(i,j,0),1);
                }
            }
            for (i = 0; i < n; ++i)
            {
                for (j = 0; j < m; ++j)
                {

                    if ((i + j)%2 == 1 && bd[i][j] != 'X')
                    {
                        if (i%2 == 0) add(s,idx(i,j,1),1);
                        else add(idx(i,j,0),e,1);


                        for (k = 0; k < 4; ++k)
                        {
                            int tx = i + dx[k];
                            int ty = j + dy[k];
                            if (tx >= 0 && tx < n && ty >= 0 && ty < m && bd[tx][ty] != 'X')
                            {
                                if (i%2 == 0)
                                add(idx(i,j,1),idx(tx,ty,1),1);
                                else
                                add(idx(tx,ty,0),idx(i,j,1),1);
                            }
                        }


                    }
                }
            }
//            printf(">>>>>>>>>>>\n");
            int ans = dinic(s,e);
            return ans;
        }


};


// Powered by FileEdit
// Powered by TZTester 1.01 [25-Feb-2003]
// Powered by CodeProcessor


// Powered by FileEdit
// Powered by TZTester 1.01 [25-Feb-2003]
// Powered by CodeProcessor

 

 

 

posted @ 2013-04-09 08:34  E_star  阅读(315)  评论(2)    收藏  举报