2016年第一次省赛训练赛

训练赛地址http://acm.hust.edu.cn/vjudge/contest/view.action?cid=108150#overview

A.FZU 2190

解题思路:

算法:单调栈

每个点预处理出当前点所在的列以当前点为结尾有多少个连续的w,下图中画圈的点就应该存3。

我们称为这个点的w值。

 

单调栈里存的是一个结构体,里面的元素分别是当前点的w,以及以当前点为结尾以w为矩形的一边,当前点的左上方能框出由w组成的最大矩形的另一边的长度,称这个值为cnt。

将以当前点为矩形的右下角,矩形的数量有num种。

每遍历到新的一行的时候清空栈。

每遍历到一个点的时候,如果这个点的w值大于上一个点,则当前点这num值应为上一点的num值加当前点的w值。

当上一点能框出如上矩形的时候,那么当前点一定对应一个如下的矩形

而包括当前点却不包括上一点的只有当前点往上连成的矩形,如下图这样

而当当前点的w值大于上一个点的w值的时候,应该把上一个点从栈中弹出,并且num减去上一点的w*cnt值,此时的num变成当前栈顶元素的num值

代码如下

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int maxa = 2005;
char str[maxa][maxa];
struct point{
    int cnt, w;
}p[maxa];
int w[maxa][maxa];
int main(){
    int n, m;
    while(scanf("%d%d", &n, &m)!=EOF){
        long long ans = 0;
        for(int i = 1; i <= n; i++){
            scanf("%s", str[i]);
            int top = 0;
            int num = 0;
            for(int k = 0;k < m; k++){
                if(str[i][k] == 'w'){
                    w[i][k] = w[i-1][k]+1;
                }else w[i][k] = 0;
                point a;
                a.w = w[i][k], a.cnt = 1;
                while(top > 0 && p[top-1].w > w[i][k]){
                    num -= p[top-1].w*p[top-1].cnt;
                    a.cnt += p[top-1].cnt;
                    top--;
                }
                p[top++] = a;
                num += a.cnt*a.w;
                //printf("%d===\n", num);
                ans += num;
            }
        }
       // printf("%lld\n", ans);
        printf("%I64d\n", ans);
    }
}
View Code

FZU 2191

暴力枚举A。a/A即为B(无限制时)在A范围内的数量,a/A如果大于等于A的话B(大于等于A)的数量就是a/A-A;
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main(){
    long long a, b;
    while(EOF!= scanf("%I64d%I64d", &a, &b)){
        long long sum = 0;
        a--;
        for(long long i = 1; i *i*i <= b; i++){
            long long  ss = 0;
            if((b / (i*i)) < i) ss = 0;
            else ss += (b / (i*i)) - i+1;
            //printf("%I64d\n", ss);
            if((a / (i*i)) < i) ;
            else ss -= (a / (i*i)) - i+1;
            sum += ss;
        }
        printf("%I64d\n", sum);
    }

}
View Code

FZU 2192

并查集

#include<stdio.h>
#include<iostream>
using namespace std;
const int maxa = 2000006;
int fa[maxa];
int find(int id){
    return fa[id] = fa[id] == id? id: find(fa[id]);
}
int main(){
    int n, m, q;
    while(scanf("%d%d%d", &n, &m , &q)!=EOF){
        for(int i = 0; i <= n+m+n+m; i++) fa[i] = i;
        for(int i = 0;i < n; i++){
            int itm, cid;
            scanf("%d%d", &itm, &cid);
            if(cid == 0 ) cid = itm;
            else cid += n+m;
            //printf("%d %d===\n", find(itm), cid);
            fa[find(itm)] =cid;
        }
        for(int i= 0; i < m; i++){
            int uid, itm, cid;
            scanf("%d%d%d", &uid, &itm, &cid);
            if(uid != 0)
            uid += n;
            if(cid != 0)
            cid += n+m;
            int ff = 0;
            ff = max(ff, find(uid));
            ff = max(ff, find(itm));
            ff = max(ff, cid);
            //printf("%d %d ===\n", find(uid), ff);
            //printf("%d %d ===\n", find(itm), ff);
            fa[find(uid)] = ff;
            fa[find(itm)] = ff;
        }
        for(int i = 0;i < q; i++){
            int a, b;
            scanf("%d%d", &a, &b);
            if(a == 1) b += n;
            int ff = find(b);
            //printf("find == %d\n", ff);
            if(ff > n+m) printf("%d\n", ff - n-m);
            else printf("0\n");
        }

    }
}
View Code

FZU 2193

#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
int main(){
    int t;
    scanf("%d", &t);
    while(t--){
        char str[100];
        scanf("%s", str);
        long long a = 1, b = 0;
        int ok = 0;
        for(int i = 0;str[i]; i++){
            if(str[i] == '.') ok = 1;
            else{
                if(ok == 1) a *= 10;
                b = b*10 + str[i] -'0';
            }
        }
        //printf("%lld %lld\n", a, b);
        long long c = __gcd(a, b);
        if(a/c == 1) printf("%I64d\n", b/c);
        else
        printf("%I64d/%I64d\n", b/c, a/c);
    }
}
View Code

FZU 2194

不会,回头补上

FZU 2195

停在距离起点权值和最大的点的时候为最少花费,最少花费为总权值减最大权值路径。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
using namespace std;
const int maxa = 100006;
vector<int> v[maxa];
vector<int> val[maxa];
int dfs(int id){
    int maxx = 0;
    for(int i = 0;i < v[id].size(); i++){
        maxx = max(maxx, val[id][i] + dfs(v[id][i]));
    }
    return maxx;
}
int main(){
    int n;
    while(scanf("%d", &n)!=EOF){
        for(int i = 1;i <= n; i++){
            v[i].clear();
            val[i].clear();
        }
        int ans = 0;
        for(int i = 1; i < n; i++){
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            v[a].push_back(b);
            val[a].push_back(c);
            ans += c;
        }
        //printf("%d\n", ans);
        //printf("%d\n" ,dfs(1));
        ans -= dfs(1);
        printf("%d\n", ans);
    }
}
View Code

FZU 2196

广搜,先求出所有点被岩浆漫过的时刻,再广搜求解,坑点在于到达终点的瞬间就可以出去而不用考虑落到终点后一秒之内是否岩浆会碰到主角。

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxa = 1005;
int visf[maxa][maxa];
int visr[maxa][maxa];
char mp[maxa][maxa];
int m, n;
struct point{
    int x, y;
    //point(int a, int b):x(a), y(b){};
}str;
queue<point> Q;
int Move[4][2] = {0, 1, 0, -1, -1, 0, 1, 0};
int judge(int i , int j){
    if(0 <= i && i < n && 0 <= j && j < m && mp[i][j] != '#') return 1;
    return 0;
}

void bfs1(){
    while(!Q.empty()){
        int x = Q.front().x;
        int y = Q.front().y;
        Q.pop();
        for(int i = 0; i < 4; i++){
            int ii = x + Move[i][0];
            int kk = y+Move[i][1];
            if(judge(ii, kk) && visf[ii][kk] == -1){
                visf[ii][kk] = visf[x][y]+1;
                point aa;
                aa.x = ii;
                aa.y = kk;
                Q.push(aa);
            }
        }
    }
}
int bfs2(point str){
    while(!Q.empty()) Q.pop();
    Q.push(str);
    while(!Q.empty()){
        int x = Q.front().x;
        int y = Q.front().y;
        if(mp[x][y] == 'E'){
            return 1;
        }
        //printf("%d %d\n", x, y);
        Q.pop();
        for(int i = 0; i < 4; i++){
            int ii = x + Move[i][0];
            int kk = y + Move[i][1];
            if(mp[ii][kk] != 'E'){
                if(visr[ii][kk] == -1 && judge(ii, kk) && (visf[ii][kk] == -1 || visr[x][y]+1 < visf[ii][kk])){
                    visr[ii][kk] = visr[x][y]+1;
                    point aa;
                    aa.x = ii;
                    aa.y = kk;
                    Q.push(aa);
                }
            }else{
                if(visr[ii][kk] == -1 && judge(ii, kk) && (visf[ii][kk] == -1 || visr[x][y]+1 <= visf[ii][kk])){
                    visr[ii][kk] = visr[x][y]+1;
                    point aa;
                    aa.x = ii;
                    aa.y = kk;
                    Q.push(aa);
                }
            }
        }
    }
    return 0;
}
int main(){
    int t;
    scanf("%d", &t);
        while(t--){
            memset(visr, -1, sizeof(visr));
            memset(visf, -1 ,sizeof(visf));
            scanf("%d%d", &n, &m);

            while(!Q.empty()) Q.pop();
            for(int i = 0; i < n; i++){
                scanf("%s", mp[i]);
                for(int k = 0; k < m; k++){
                    if(mp[i][k] == 'S'){
                        str.x = i, str.y = k;
                        visr[i][k] = 0;
                    }
                    if(mp[i][k] == '!'){
                        visf[i][k] = 0;
                        point aa; aa.x = i, aa.y = k;
                        Q.push(aa);
                    }
                }
            }
            bfs1();
            //printf("dd");
            if(bfs2(str))printf("Yes\n");
            else printf("No\n");

        }
return 0;
}
View Code

FZU 2197

设1的个数为num1,则在前num1位置的1不用移动,后面的1移动到离其最近的零(前num1中)一定是最优解。

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxa = 100005;
char str[maxa];
int main(){
    int t;
    scanf("%d", &t);
    while(t--){
        int a, b;
        scanf("%d%d", &a, &b);
        scanf("%s", str);
        int num1 = 0;
        for(int i = 0; str[i]; i++){
            num1 += str[i] - '0';
        }
        long long ans = 0;
        int l = num1 - 1;
        for(int i = num1; str[i]; i++){
            if(str[i] == '1'){
                while(str[l] !='0'){
                    l--;
                }
                //printf("l == %d\n", l);
                ans += min((i - l) *a, b);
                l--;
            }
        }
        printf("%I64d\n", ans);
    }
}
View Code

 

posted @ 2016-03-08 20:04  icodefive  阅读(247)  评论(0)    收藏  举报