zoukankan      html  css  js  c++  java
  • Codeforces Round #161 (Div. 2)

    A.Beautiful Matrix  

    如果1的位置在Matrix中为x,y(从1开始计数),答案为abs(3-x)+abs(3-y)

    B.Squares  

    满足所选的点要包含在对角点(0,0)到(ai,ai)这样的刚好k个正方形内(边界也算),降序sort一遍a数组,输出(a[k-1],a[k-1])或者(a[k-1],0)什么的都行

    C.Circle of Numbers    

    构造出满足题意的序列就可以,因为不限制排列开始的元素位置,不限制顺时或是逆时,所以直接可以让1是第一个元素,tutorial里的方法是分情况判断构造出第二三个元素,然后依约束的关系去恢复剩下的元素。刚开始要去判断每个元素是否仅仅出现的4次,否则-1.

    这里我用的dfs+回溯的方法来做,虽然元素很多,但是每个元素相连接的点只有4个,还比较快。

    用vis数组标记使用过的元素

    对于Ans中只有1个元素时候,第2个元素需要满足,link[1]中包含元素2,搜的时候就是按照邻接关系来搜的,这是必然的。

    对于Ans中多于1个元素的时候,每添加一个新元素,如 A B C(Prepare to add),需要约束条件link[A]中包含A、C,link[B]中包含C.

    不断的搜索直到Ans的大小为n时,答案就有了。

    但是某些组合满足每个元素都出现4次,但是也可能构造不出圈,所以我对于那些没有printf出答案然后exit(0)的数据,后面补一个-1.

    View Code
    vector<int> link[100005];
    int cnt[100005];
    int vis[100005];
    vector<int> ans;
    int n;
    
    int has(vector<int> e, int val)
    {
        for(int i = 0; i < e.size(); i++)
            if(e[i] == val)    return 1;
        return false;
    
    }
    
    void dfs(int val)
    {
        int i;
        vis[val] = 1;
        ans.push_back(val);
    //     for(i = 0;i < ans.size(); i++)
    //         printf("%d ", ans[i]);
    //     printf("\n");
        if(ans.size() == n)    
        {
            for(i = 0;i < n; i++)
                printf("%d ", ans[i]);
            printf("\n");
            exit(0);
        }
        
        for(i = 0; i < link[val].size(); i++)
        {
            if(!vis[ link[val][i] ] && ans.size() <= 1)
            {
                dfs( link[val][i] );
                vis[ link[val][i] ] = 0;
                ans.pop_back();
            }
            else if(!vis[ link[val][i] ] && ans.size() >= 2)
            {
                if(has( link[ ans[ ans.size()-2 ] ], ans[ ans.size()-1 ] ) && has(link[ ans[ans.size()-2] ], link[val][i]) 
                    &&    has( link[ ans[ ans.size()-1 ] ], link[val][i]) )
                {
                    dfs( link[val][i] );
                    vis[ link[val][i] ] = 0;
                    ans.pop_back();
                }
            }
        }
    }
    
    int main()
    {
        int a,b,i;
        get(n);
        memset(cnt,0,sizeof(cnt));
        memset(vis,0,sizeof(vis));
        for(i = 0; i < 2*n; i++)
        {
            get(a);get(b);
            cnt[a]++; cnt[b]++;
            link[a].push_back(b);
            link[b].push_back(a);
        }
        int ok = 1;
        for(i = 1; i <= n; i++)
        {
            if(cnt[i] != 4)
            {
                ok = 0;
                break;
            }
        }
        if(!ok)    printf("-1\n");
        else
        {
            dfs(1);
            printf("-1\n");
        }
        return 0;
    }

    D.Cycle in Graph  

    给一个无向图,求某个输出某个环,长度 ≥ k+1.

    如果存在一条路径v1,v2,...,vr,若vr的相邻点中包括v1,那么就至少形成了一个长度为r的环,只要r ≥ k+1满足题意输出答案就可以了。

    用DFS+回溯的方法去搜索这样可能的路径。

    View Code
    /*
    DFS+回溯,找出大于等于k+1的环。
    */
    
    vector< int > adj[100005];
    vector< int > path;
    int vis[100005];
    int k;
    
    void dfs(int cur,int len)
    {
        int i,j;
        path.push_back(cur);
        vis[cur] = 1;
        len++;
        if(len >= k+1)
        {
            for(i = 0; i < adj[cur].size(); i++)    
            {
                if(adj[cur][i] == path[0])
                {
                    printf("%d\n", len);
                    for(j = 0; j < path.size(); j++)
                        printf("%d ", path[j]);
                    printf("\n");
                    exit(0);
                }
            }
        }
        for(i = 0; i < adj[cur].size(); i++)
        {
            if(!vis[adj[cur][i]])    dfs(adj[cur][i],len);
        }
        vis[cur] = 0;
        path.pop_back();
    }
    
    int main()
    {
        int a,b,i,m,n;
        get(n);get(m);get(k);
        memset(vis,0,sizeof(vis));
        for(i = 1; i <= m; i++)
        {
            get(a);get(b);
            adj[a].push_back(b);
            adj[b].push_back(a);
        }
        for(i = 1; i <= n; i++)
            dfs(i,0);
        return 0;
    }

    E.Rhombus

    解题的方法,就和题目意思一样,从菱形的角度来考虑。

      ≥ 0, 而是坐标(i, j)到坐标(x, y)的曼哈顿距离,约束出来是一个菱形。

    当k = 2时候,这个式子在(x,y)处表达的图案如下

    在该点处f(x,y) = 2*ax,y + 1*(ax-1,y-1 + ax+1,y-1 + ax-1,y+1 + ax+1,y+1) , 所以依次类推。

    把菱形按照距离相关的权值,从大到小把菱形分圈,每个权值圈,找出它的ai,j的总和,然后在和权值运算。

    可以数组记录,斜左下,斜右下的递增和,这样求菱形每一遍和时候,每一段只用O(1)就可以求出。

    最后brute force,遍历能取的所有位置,记录最大值出现位置。

    搓方法,O(n3),2781ms跑完所有数据,接近超时了。Tutorial 方法更好一些。

    View Code
    #define _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <iomanip>
    #include <vector>
    #include <deque>
    #include <list>
    #include <set>
    #include <map>
    #include <stack>
    #include <queue>
    #include <bitset>
    #include <string>
    #include <numeric>
    #include <functional>
    #include <iterator>
    #include <typeinfo>
    #include <utility>
    #include <memory>
    #include <cmath>
    #include <cstdlib>
    #include <cctype>
    #include <cstddef>
    #include <complex>
    #include <ctime>
    #include <cassert>
    using namespace std;
    
    typedef __int64 LL;
    static inline bool get(int &v)
    {
        int s = 1, c;
        while(!isdigit(c = getchar())&&c != '-')
        {
            if(c == EOF)
                break ;
        }
        if(c == EOF) return 0;
        if(c == '-') s = 0 , v = 0;
        else v = c^48;
        for(;isdigit(c = getchar());v = (v << 1) + (v << 3) + (c ^ 48));
        v = (s ? v : -v);
        return 1 ;
    }
    
    struct st
    {
        int val;
        LL l;
        LL r;
    }matrix[1005][1005];
    
    void init(int n,int m)
    {
        int i, j;
        for(i = 0; i <= n; i++)
        {
            for(j = 0; j <= m+1; j++)
            {
                matrix[i][j].val = 0;
                matrix[i][j].l = 0;
                matrix[i][j].r = 0;
            }
        }
    }
    
    int main()
    {
        int n,m,k,i,j,v,a,b;
        get(n);get(m);get(k);
        init(n,m);
        for(i = 1; i <=  n; i++)
        {
            for(j = 1; j <= m; j++)
            {
                get(matrix[i][j].val);
                matrix[i][j].l = matrix[i-1][j+1].l + matrix[i][j].val;
                matrix[i][j].r = matrix[i-1][j-1].r + matrix[i][j].val;
            }
        }
        LL ans = 0;
        a = k;
        b = k;
        for(i = k; i <= n-k+1; i++)
            for(j = k; j <= m-k+1; j++)
            {
                LL res = 0;
                for(v = k; v >= 1; v--)
                {
                    if(v == k)
                    {
                        res += k*matrix[i][j].val;
                    }
                    else
                    {
                        LL tmp = 0;
                        tmp += matrix[i][j-(k-v)].l - matrix[i-(k-v)][j].l;
                        tmp += matrix[i+(k-v)][j].l - matrix[i][j+(k-v)].l;
                        tmp += matrix[i+(k-v)][j].r - matrix[i][j-(k-v)].r;
                        tmp += matrix[i][j+(k-v)].r - matrix[i-(k-v)][j].r;
                        tmp += matrix[i-(k-v)][j].val;
                        tmp -= matrix[i+(k-v)][j].val;
                        res += v*tmp;
                    }
                }
                //printf("%d\n" ,res);
                if(res > ans)
                {
                    ans = res;
                    a = i;
                    b = j;
                }
            }
            printf("%d %d\n", a,b);
            return 0;
    }
  • 相关阅读:
    ABAP 获取当天的上一个工作日或下一个工作日
    ABAP 增强实战:Enhancement Implementation增强点实施例子
    ABAP Alv输出金额字段时,需要按国家的货币格式显示,列如:JPY
    ABAP 调用程序时获取的数量,金额和日期字段会出现 逗号,-,负号等非法字段,所需要进行转化
    ABAP 调用标准报表程序,获取程序输出list
    ABAP Alv Varient问题:可以更改alv字段布局然后存到Varient中
    ABAP 向下取整和向上取整及取余数
    传统视觉处理方法笔记
    图像特征与描述笔记
    图像预处理笔记
  • 原文地址:https://www.cnblogs.com/tiny656/p/2864087.html
Copyright © 2011-2022 走看看