noip刷题记录 20170823

Posted CzYoL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了noip刷题记录 20170823相关的知识,希望对你有一定的参考价值。

独木桥

怎么说呢

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int N = 5050;
int n, l, pos[N], maxx = 0, minn = 0;

int main(){
    scanf("%d%d", &l, &n);
    for(int i = 1; i <= n; i++) scanf("%d", &pos[i]);
    sort(pos + 1, pos + n + 1);
    for(int i = 1; i <= n; i++)
        if(pos[i] <= (1 + l) / 2) maxx = max(maxx, l - pos[i] + 1), minn = max(pos[i], minn);
        else maxx = max(maxx, pos[i]), minn = max(minn, l - pos[i] + 1);
    printf("%d %d", minn, maxx);
    return 0;
}

 

传纸条 & 方格取数

多维dp的应用

code传纸条

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

const int N = 60;
int n, m, a[N][N], dp[N][N][N][N];

inline int myMax(int u, int v, int x, int y){
    int ret = u;
    ret = max(ret, v);
    ret = max(ret, x);
    ret = max(ret, y);
    return ret;
}

int main(){
    scanf("%d%d", &m, &n);
    for(int i = 1; i <= m; i++)
        for(int j = 1; j <= n; j++)
            scanf("%d", &a[i][j]); 
    dp[1][1][1][1] = a[1][1];
    for(int i = 1; i <= m; i++)
        for(int j = 1; j <= n; j++)
            for(int k = 1; k <= m; k++)
                for(int l = 1; l <= n; l++){
                    if(i == 1 && j == 1) continue;
                    dp[i][j][k][l] = myMax(dp[i - 1][j][k - 1][l], dp[i][j - 1][k - 1][l],
                                           dp[i - 1][j][k][l - 1], dp[i][j - 1][k][l - 1])
                                     + a[i][j] + a[k][l];
                    if(i == k && j == l)
                        dp[i][j][k][l] -= a[i][j];    
                }
    printf("%d", dp[m][n][m][n]);
    return 0;
}

 code方格取数

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

const int N = 15;
int n, a[N][N], dp[N][N][N][N];

inline int myMax(int u, int v, int x, int y){
    int ret = u;
    ret = max(ret, v);
    ret = max(ret, x);
    ret = max(ret, y);
    return ret;
}

int main(){
    scanf("%d", &n);
    int x, y, w;
    while(scanf("%d%d%d", &x, &y, &w), x + y + w)
        a[x][y] = w;
//    dp[1][1][1][1] = a[1][1];
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            for(int k = 1; k <= n; k++)
                for(int l = 1; l <= n; l++){
//                    if(i == k && j == l && i != n && j != n) continue;
                    dp[i][j][k][l] = myMax(dp[i - 1][j][k - 1][l], dp[i][j - 1][k - 1][l],
                                           dp[i - 1][j][k][l - 1], dp[i][j - 1][k][l - 1])
                                     + a[i][j] + a[k][l];
                    if(i == k && j == l )
                        dp[i][j][k][l] -= a[i][j];    
                }
    printf("%d", dp[n][n][n][n]);
    return 0;
}

 

 矩阵取数游戏

问题识破 + dp + 高精度

技术分享
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;

inline int read(){
    int i = 0, f = 1; char ch = getchar();
    for(; (ch < 0 || ch > 9) && ch != -; ch = getchar());
    if(ch == -) f = -1, ch = getchar();
    for(; ch >= 0 && ch <= 9; ch = getchar())
        i = (i << 3) + (i << 1) + (ch - 0);
    return i * f;
}

const int N = 100;
int n, m;

struct bign{
    int len, s[N];
    bign():len(1){memset(s, 0, sizeof s);}
    inline void clear(){
        while(len > 1 && s[len] == 0) len--;
    }
    inline bign operator * (const bign &u) const{
        bign ret;
        ret.len = len + u.len + 10;
        for(int i = 1; i <= len; i++)
            for(int j = 1; j <= u.len; j++)
                ret.s[i + j - 1] += s[i] * u.s[j];
        for(int i = 1; i <= ret.len; i++)
            if(ret.s[i] >= 10){
                ret.s[i + 1] += ret.s[i] / 10;
                ret.s[i] %= 10;
            }
        ret.clear();
        return ret;
    }
    inline void print(){
        clear();
        for(int i = len; i >= 1; i--)
            putchar(s[i] + 0);
    }
    inline bool operator > (const bign &u) const{ 
        if(len != u.len) return len > u.len;
        for(int i = len; i >= 1; i--)
            if(s[i] != u.s[i]) return s[i] > u.s[i];
        return false;
    }
    inline bign operator + (const bign &u) const{
        bign ret;
        ret.len = 0;
        int i, g;
        for(i = 1, g = 0; g || i <= max(len, u.len); i++){
            ret.s[++ret.len] = g;
            if(i <= len) ret.s[ret.len] += s[i];
            if(i <= u.len) ret.s[ret.len] += u.s[i];
            g = ret.s[ret.len] / 10;
            ret.s[ret.len] %= 10;
        }
        ret.clear();
        return ret;
    }
}pow2[N][N], f[N][N], big2, ans, ret, a[N], big0;

inline bign newBign(int x){
    bign ret;
    ret.len = 0;
    while(x){
        ret.s[++ret.len] = x % 10;
        x /= 10;
    }
    if(ret.len == 0) ret.len = 1;
    return ret;
}

inline void initPow(){
    for(int i = 1; i <= m; i++)
        for(int j = 1; j <= m; j++)
            pow2[i][j] = pow2[i][j - 1] + pow2[i][j - 1];
}

inline bign max(bign a, bign b){
    return a > b ? a : b;
}

int main(){
    n = read(), m = read();
    ans = big0 = newBign(0); big2 = newBign(2);
    for(int t = 1; t <= n; t++){
        ret = big0;
        for(int i = 1; i <= m; i++) pow2[i][0] = newBign(read());
        initPow();
        for(int i = 0; i <= m; i++)
            for(int j = 0; j <= m; j++)
                f[i][j] = big0;
        for(int i = 0; i <= m; i++)
            for(int j = 0; i + j <= m; j++){
                if(i > 0) f[i][j] = max(f[i - 1][j] + pow2[i][i + j], f[i][j]);
                if(j > 0) f[i][j] = max(f[i][j - 1] + pow2[m - j + 1][i + j], f[i][j]);
            }
        for(int i = 0; i <= m; i++)
            ret = max(ret, f[i][m - i]);
        ans = ans + ret;
    }
    ans.print();
    return 0;
}
View Code

 

铺地毯

怎么说呢

#include<iostream>
#include<cstdio>
using namespace std;

const int N = 1e4 + 5;
int n, x1[N], y1[N], l[N], w[N], x, y, ans = -1;

int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%d%d%d%d", &x1[i], &y1[i], &l[i], &w[i]);
    scanf("%d%d", &x, &y);
    for(int i = n; i >= 1; i--){
        if(x1[i] <= x && x <= x1[i] + l[i] - 1 && y1[i] <= y && y <= y1[i] + w[i] - 1){
            ans = i;
            break;
        }
    }
    printf("%d", ans);
    return 0;
}

以上是关于noip刷题记录 20170823的主要内容,如果未能解决你的问题,请参考以下文章

Loj一本通刷题记录

愿你那可爱的光明前途——十二月刷题记录

2017年11月1日刷题记录 | 普及组

20170823 - Q - 日期操作

20170823 - A - 日期操作

刷题总结——子串(NOIP2015)