• UESTC 2014 Summer Training #6 Div.2


      又是只过两水题,不过状态有些回升,也是差点一血.

    Problem A  SPOJ AMR11A

      显然的dp?就一抖就想到尝试从(R,C)推到(1,1),正着推的话,只能检查某一种解可不可行(就有人想出了二分+DP的神奇方法。。刚卡过。。不过上界是把所有龙加起来。。不闲麻烦的话。。可以按照贪心的方法先跑一个上界,就每一步选当前最优)

      倒着推,龙的话,就加上,药水的话,减去?不够,和1取最大值;某一个点的f[i][j]就是两种策略取最小值;

      f[i][j] = min{ max(1, f[i+1][j]-s[i][j]) ,  max(1, f[i][j+1]-s[i][j] }

      题外话:  自己是12:24提交的这代码。。不过不是scanf,是cin,然后又提交了一个递推的,还是TLE。。。于是就去写水题,写了水题回来写。。。居然会去写搜索。。主要看大家都没怎么过。。以为不是这么简单的dp 0 0 写了好几个小时,想到了求出那个上界的方法,以后搜索优化也许可以用。。不过对这题没什么帮助,后来又去研究卡时。。总之挂很惨。。差一点一血啊

    (记忆化)

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    
    const int maxn = 500+10;
    const int inf = ~0u >> 2;
    
    int T, r, c, ans;
    int f[maxn][maxn], s[maxn][maxn];
    
    int dp(int x, int y)
    {    
    //    cout << "dp " << x << ' ' << y << endl;
        if(x > r || y > c)    return inf;
        if(f[x][y] != inf)    return f[x][y];
        return    f[x][y] = min(max(dp(x+1, y)-s[x][y], 1), max(dp(x, y+1)-s[x][y], 1));
    }
    
    int main()
    {
    #ifdef LOCAL
        freopen("A.in", "r", stdin);
    #endif 
        cin >> T;
        while(T--) {
            cin >> r >> c;
            for(int i = 1; i <= r; i++)
                for(int j = 1; j <= c; j++)
                    f[i][j] = inf;
            f[r][c] = 1;
            for(int i = 1; i <= r; i++)
                for(int j = 1; j <= c; j++)
                    scanf("%d", s[i]+j);
            cout << dp(1, 1) << endl;
        }
        return 0;
    }


    Problem B  SPOJ AMR11B

     

      大意是给你圆(圆心+半径)、三角形(三点)、正方形(左下角和边长),球出覆盖的点数,只用考虑整数,包括给的数据

      由于数据很小,我们可以求出其外接?的矩形,枚举点再来判定是否在图形内,需要做判重处理。

      圆用x^2+y^2=R^2这种公式就行了,正方形直接枚举的点就是图形内的(包括边界),主要是三角形比较麻烦,需要用到前几天考察过的计算几何的知识(我都还没写解题报告。。)

      判断三个小三角形面积和是否等于大三角形面积。面积的求法只能暂且记住,好像算是线性代数的知识0 0 都没印象。

      S=|(y3-y1)*(x2-x1)-(y2-y1)*(x3-x1)|/2  (在这道题的情况下,就别/2咯)

      奥,把坐标系移动下,c语言数组不好处理负数呢

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <ctype.h>
    
    using namespace std;
    
    const int maxn = 400;
    
    int T, n, cnt;
    bool used[maxn][maxn];
    
    void calcSquare()
    {
        int x, y, l;
        scanf("%d%d%d", &x, &y, &l);
        x += 100;    y += 100;
        for(int i = 0; i <= l; i++)
            for(int j = 0; j <= l; j++)
                if(!used[x+i][y+j]) {
                    used[x+i][y+j] = 1;
                    cnt++;
                }
    } 
    
    void calcCircle()
    {
        int x0, y0, r;
        scanf("%d%d%d", &x0, &y0, &r);
        x0 += 100;    y0 += 100;
        int x = x0-r, y = y0-r, l = 2*r;
        for(int i = 0; i <= l; i++)
            for(int j = 0; j <= l; j++) {
    //            if(i == 1 && j == 2)    cout << ( !used[x+i][y+i] && (x+i-x0)*(x+i-x0)+(y+j-y0)*(y+j-y0) <= r*r ) << endl;
    
    //                int a = (x+i-x0)*(x+i-x0)+(y+j-y0)*(y+j-y0), b = r*r;
    //                cout << x+i << ' ' << y+j << ' ' << a << ' ' << b << endl;
                if(!used[x+i][y+j] && (x+i-x0)*(x+i-x0)+(y+j-y0)*(y+j-y0) <= r*r) {
    //                if( (x+i-x0)*(x+i-x0)+(y+j-y0)*(y+j-y0) > r*r)
                    //if(a > b)    continue;
    //                cout << "COUNT" << endl;
    //                cout << "Change " << x+i << ' ' << y+j << endl;
                    used[x+i][y+j] = 1;
    //                cout << "Change " << x+i << ' ' << y+j << endl;
                    cnt++;
                }
            }
    }
    
    int area(int x1, int y1, int x2, int y2, int x3, int y3)
    {
        //notice real area is this one divide 2
        return abs((y3-y1)*(x2-x1)-(y2-y1)*(x3-x1));
    }
    
    void calcTriangle()
    { 
        int x1, x2, x3, y1, y2, y3;
        scanf("%d%d%d%d%d%d", &x1, &y1, &x2, &y2, &x3, &y3);
        x1 += 100;    y1 += 100;    x2 += 100;    y2 += 100;    x3 += 100;    y3 += 100;
        int a, b, c, d;
        a = min(x1, min(x2, x3));    b = min(y1, min(y2, y3));
        c = max(x1, max(x2, x3));    d = max(y1, max(y2, y3));
        for(int i = a; i <= c; i++)
            for(int j = b; j <= d; j++)
                if(!used[i][j]) {
                    if(area(i, j, x1, y1, x2, y2) + area(i, j, x2, y2, x3, y3) + area(i, j, x1, y1, x3, y3) != area(x1, y1, x2, y2, x3, y3))
                        continue;
                    used[i][j] = 1;
                    cnt++;
                }
    }
    
    int main()
    {
    #ifdef LOCAL
        freopen("B.in", "r", stdin);
    #endif 
        scanf("%d", &T);
        while(T--) {
            scanf("%d", &n);
            cnt = 0;
            memset(used, 0, sizeof(used));
            while(n--) {
                char c;
                while(!isalpha(c = getchar())) ; 
                switch(c) {
                    case 'C':    calcCircle();    break;
                    case 'T':    calcTriangle();    break;
                    case 'S':    calcSquare();    break;
                    default:    break;
                }
            }
            printf("%d
    ", cnt);
        }
        return 0;
    }

    Problem E  SPOJ AMR11E

      找出第n个幸运数(因子中至少能找出3个不同的质数) 

      由于n比较小,我直接打表出1000个幸运数。。。打表写得比较渣。一开始还写错了。代码不贴咯。

    Problem G  SPOJ AMR11G

      就水题。。。判断下有没D  vjudge爬虫代码估计渣了,Sample Input格式有点问题,害得我代码调了很久

    //  cin.getline(str, [length], [endcharacter])(会读入endcharacter)

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int maxn = 100;
    
    int T, N;
    char c;
    
    int main()
    {
    #ifdef LOCAL
        freopen("G.in" , "r", stdin);
    #endif
        cin >> T;
        cin.ignore();
        while(T--) {
             {
                char s[maxn];
                cin.getline(s, maxn);
    //            cout << s << endl;
    //            cin.ignore();
                bool ok = true;        
                for(unsigned int i = 0; i < strlen(s); i++)
                    if(s[i] == 'D') {
                        ok = false;
                        break;
                    }
                if(!ok)    cout << "You shall not pass!" << endl;
                else    cout << "Possible" << endl;
            }
        }
        return 0;
    }

    Problem J  SPOJ AMR11J

      比较裸的bfs,数据量不大,不用担心什么,关键是策略写对没。

      主要问题在于两个部落同时expand到一点时,会冲突,标记为'*',而bfs是有先后的,除非多线程?

      所以需要延时处理,记录要更新的地点,记录下要更新 为 的标记:另开一个数组,先到先标记,后到发现已标记就置为'*’

      !!!!这里思路就又错了,逻辑不紧哎。  发现标记不同才置为'*'

      否则会出现b.b  ->  b*b

      

    (可能是vector降低了效率,跑得比较慢)

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<vector>
    #include<queue>
    #include<utility>
    #include<cstring>
    
    using namespace std;
    
    const int maxn = 500+10;
    const int dx[] = {1, -1, 0, 0};
    const int dy[] = {0, 0, 1, -1};
    
    typedef pair<int, int> pii;
    
    int T, R, C;
    char m[maxn][maxn], ocp[maxn][maxn];
    vector<pii>    v;
    queue<pii> q;
    
    void update()
    {
        for(int i = 0, t = v.size(); i < t; i++) {
            int x = v[i].first, y = v[i].second;
            if(m[x][y] == '.') {
                m[x][y] = ocp[x][y]; 
                q.push(make_pair(x, y));
            }
        }
        v.clear();
    }
    
    bool can_move(int x, int y)
    {
        return x >= 1 && x <= R && y >= 1 && y <= C && m[x][y] == '.';
    }
    
    void bfs()
    {
        for(int i = 1; i <= R; i++)
            for(int j = 1; j <= C; j++)
                if(m[i][j] <= 'z' && m[i][j] >= 'a')
                    q.push(make_pair(i, j));
        while(!q.empty()) {
            pii tmp = q.front();    q.pop();
            int x = tmp.first, y = tmp.second;
            for(int i = 0; i < 4; i++) {
                int nx = x+dx[i], ny = y+dy[i];
                if(can_move(nx, ny)) {
                    if(ocp[nx][ny] && ocp[nx][ny] != m[x][y])
                        m[nx][ny] = '*';            
                    else {
                        v.push_back(make_pair(nx, ny));
                        ocp[nx][ny] = m[x][y];
                    }
                }
            }
            if(q.empty())    update();
        }
    }
    
    int main()
    {
    #ifdef LOCAL
        freopen("J.in", "r", stdin);
    #endif
        cin >> T;
        while(T--) {
            cin >> R >> C;
            while(!q.empty())    q.pop();
            v.clear();
            memset(ocp, 0, sizeof(ocp));
            for(int i = 1; i <= R; i++)
                    cin >> (m[i]+1);
            bfs();
            for(int i = 1; i <= R; i++)
                cout << (m[i]+1) << endl;
        }
        return 0;
    }


      A题瞄一眼思路就来了,所以直接写的A,无奈犯傻逼,数据量高达500*500=250000 25W啊 TLE得没办法

      然后去跟榜做E、G,E题打表因为自己没读透题,浪费很多时间,这一来一去心态乱了很多。总感觉自己能写A,再去搞没办法又搜索又减枝,反正搞到快4点也一直TLE

      心态真的崩了,一开始以为能做的题,结果卡了这么久,我交了43发。。。彻底蒙了。还有一丝理智,去看J,又慌了!根本不用考虑time的,还去傻逼写优先队来保证每次出队是time最小的,其实就是跟新完一圈又跟新下一圈。不过无伤大雅,有个小错误没时间去发现了。2题GG。rank又垫底。

      心态这玩意,真的不是一两天能改好的,也要看比赛的重要性,多加控制吧。

      自己读题问题也很大的,时常没考虑好就去写。写完样例一跑就傻逼。

      策略:

      问题在于有灵感想出大概思路的时候,不要抢着去写,再读题,再跑样例,理清思路再写代码,最后思考极限数据(也可以一开始就有考虑)

      其实这种策略不是一次想提出,关键是自己执行力度,容易忘掉。

      经常总结才行!

  • 相关阅读:
    【APP问题定位(三)】adb安装
    【APP问题定位(一)】夜神模拟器安装及问题
    selenium_Alert
    selenium-iframe操作
    Python+selenium打开网页
    selenium 之 ActionChains (二)
    PyCharm汉化、破解教程
    selenim之ActionChains(一)
    C#连接数据库以及增、删、改、查操作
    C#飞行棋游戏
  • 原文地址:https://www.cnblogs.com/gemmeg/p/3857267.html
Copyright © 2020-2023  润新知