zoukankan      html  css  js  c++  java
  • 叉姐的魔法训练(第三课)---- 火球术入门

    -----------------------------------------

    一 双向贪心

    POJ 3040 Allowance

    从大到小贪心选取一次,从小到大选取一次。

    缺少证明。。。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    const int maxn=41;
    const int INF=0x3f3f3f3f;
    typedef long long LL;
    typedef pair<int,int> PII;
    PII a[maxn];
    int use[maxn];
    int n,c;
    int main()
    {
        while (~scanf("%d%d",&n,&c)){
            for (int i=1;i<=n;i++){
                scanf("%d%d",&a[i].first,&a[i].second);
            }
            sort(a+1,a+n+1);
            int ans=0;
            while (1){
                memset(use,0,sizeof(use));
                int rest=c;
                for (int i=n;i>=1;i--){
                    int tmp=min(rest/a[i].first,a[i].second);
                    rest-=tmp*a[i].first;
                    use[i]=tmp;
                }
                if (rest){
                    for (int i=1;i<=n;i++){
                        if (a[i].second&&a[i].first>=rest){
                            use[i]++;
                            rest=0;
                            break;
                        }
                    }
                }
                if (rest) break;
                int Min=INF;
                for (int i=1;i<=n;i++){
                    if (use[i]){
                        Min=min(Min,a[i].second/use[i]);
                    }
                }
                ans+=Min;
                for (int i=1;i<=n;i++){
                    if (use[i]){
                        a[i].second-=use[i]*Min;
                    }
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    


    -----------------------------------------

    二 分层搜索

    POJ 3182 The Grove


    找到最上排最左边的障碍,向右虚拟一个楼梯,将图分为两层即可广搜。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cstdlib>
    #include <queue>
    using namespace std;
    
    const int maxn=51;
    const int INF=0x3f3f3f3f;
    const int direct[8][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
    
    struct Point{
        int x,y,c,s;
        Point(){}
        Point(int x,int y,int c,int s){
            this->x=x;
            this->y=y;
            this->c=c;
            this->s=s;
        }
    };
    
    int n,m;
    bool vis[maxn][maxn][2];
    char map[maxn][maxn];
    int sx,sy;
    int dx,dy;
    queue<Point>que;
    
    void init(){
        memset(vis,0,sizeof(vis));
        while (!que.empty()) que.pop();
    }
    
    void canNotMove(){
        for (int i=1;i<=n;i++){
            for (int j=1;j<=m;j++){
                if (map[i][j]=='X'){
                    dx=i;
                    dy=j;
                    return;
                }
            }
        }
    }
    
    bool input(){
        if (~scanf("%d%d",&n,&m)){
            for (int i=1;i<=n;i++) scanf("%s",map[i]+1);
            return true;
        }
        return false;
    }
    void findStart(){
        for (int i=1;i<=n;i++){
            for (int j=1;j<=m;j++){
                if (map[i][j]=='*'){
                    sx=i;
                    sy=j;
                    return;
                }
            }
        }
    
    }
    
    bool check(Point p){
        if (p.x>=1&&p.x<=n&&p.y>=1&&p.y<=m) return true;
        return false;
    }
    bool online(Point p){
        if (p.x==dx&&p.y>=dy) return true;
        return false;
    }
    int bfs(){
        vis[sx][sy][0]=true;
        que.push(Point(sx,sy,0,0));
        while (!que.empty()){
            Point frt=que.front();
            que.pop();
            for (int i=0;i<8;i++){
                Point p=frt;
                p.x+=direct[i][0];
                p.y+=direct[i][1];
                p.s+=1;
                if (!check(p)||map[p.x][p.y]=='X') continue;
                if (p.x==frt.x+1&&!online(frt)&&online(p)) continue;
                if (p.x==frt.x-1&&online(frt)&&!online(p)) p.c=1;
                if (vis[p.x][p.y][p.c]) continue;
                if (p.x==sx&&p.y==sy&&p.c==1) return p.s;
                vis[p.x][p.y][p.c]=true;
                que.push(p);
            }
        }
        return -1;
    }
    
    int main()
    {
        while (input()){
            init();
            canNotMove();
            findStart();
            printf("%d
    ",bfs());
        }
        return 0;
    }
    


    -----------------------------------------

    三 模拟神题

    POJ 2434 Waves

    题解和代码摘自网络

    要注意同一个波源发出的波反弹回来的时候是可以叠加或者相消的。

    每个石头可以分为两个波,一个高峰波,一个低谷波。
    每个波可以分为很多个水平方向的波。
    每个水平方向的波有三种情况,起始点的位置:
    1. 位于 B1 左边
    2. 位于 B1,B2 中间
    3. 位于 B2 右边

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    int map[9][9];
    int rx[5], ry[5], rt[5], bk1, bk2;
    int vali (int x)
    {
        if (x >= -4 && x <= 4) return 1;
        else return 0;
    }
    void radix (int *row, int y, int t, int rec)
    {
        int i, phi, tm, x, dir;
        int u1, u2, d1, d2;
        phi = (t - rt[rec]) - abs(y - ry[rec]);
        if (rx[rec] < bk1)
        {
            u1 = rx[rec] - phi;
            u2 = rx[rec] + phi;
            d1 = rx[rec] - phi + 2;
            d2 = rx[rec] + phi - 2;
            if (u2 >= bk1) u2 = bk1 + bk1 - 1 - u2;
            if (d2 >= bk1) d2 = bk1 + bk1 - 1 - d2;
            if (phi >= 0 && vali(u1)) row[u1 + 4]++;
            if (phi >= 1 && vali(u2)) row[u2 + 4]++;
            if (phi >= 2 && vali(d1)) row[d1 + 4]--;
            if (phi >= 3 && vali(d2)) row[d2 + 4]--;
            return;
        }
        else if (rx[rec] > bk2)
        {
            u1 = rx[rec] - phi;
            u2 = rx[rec] + phi;
            d1 = rx[rec] - phi + 2;
            d2 = rx[rec] + phi - 2;
            if (u1 <= bk2) u1 = bk2 + bk2 + 1 - u1;
            if (d1 <= bk2) d1 = bk2 + bk2 + 1 - d1;
            if (phi >= 0 && vali(u1)) row[u1 + 4]++;
            if (phi >= 1 && vali(u2)) row[u2 + 4]++;
            if (phi >= 2 && vali(d1)) row[d1 + 4]--;
            if (phi >= 3 && vali(d2)) row[d2 + 4]--;
            return;
        }
        else
        {
            u1 = rx[rec] - phi;
            u2 = rx[rec] + phi;
            d1 = rx[rec] - phi + 2;
            d2 = rx[rec] + phi - 2;
            while (1)
            {
                if (u1 <= bk1) u1 = bk1 + bk1 + 1 - u1;
                else break;
                if (u1 >= bk2) u1 = bk2 + bk2 - 1 - u1;
                else break;
            }
            while (1)
            {
                if (d1 <= bk1) d1 = bk1 + bk1 + 1 - d1;
                else break;
                if (d1 >= bk2) d1 = bk2 + bk2 - 1 - d1;
                else break;
            }
            while (1)
            {
                if (u2 >= bk2) u2 = bk2 + bk2 - 1 - u2;
                else break;
                if (u2 <= bk1) u2 = bk1 + bk1 + 1 - u2;
                else break;
            }
            while (1)
            {
                if (d2 >= bk2) d2 = bk2 + bk2 - 1 - d2;
                else break;
                if (d2 <= bk1) d2 = bk1 + bk1 + 1 - d2;
                else break;
            }
            if (phi >= 0 && vali(u1)) row[u1 + 4]++;
            if (phi >= 1 && vali(u2)) row[u2 + 4]++;
            if (phi >= 2 && vali(d1)) row[d1 + 4]--;
            if (phi >= 3 && vali(d2)) row[d2 + 4]--;
            return;
        }
    }
    int main ()
    {
        int p, time, t, i, j;
        scanf("%d %d %d %d", &p, &bk1, &bk2, &time);
        if (bk1 > bk2)
        {
            t = bk1;
            bk1 = bk2;
            bk2 = t;
        }
        for (i = 0; i < p; i++)
            scanf("%d %d %d", &rx[i], &ry[i], &rt[i]);
        memset(map, 0, sizeof(map));
        for (i = 0; i < p; i++)
        {
            for (j = -4; j <= 4; j++)
                radix(map[j + 4], j, time, i);
        }
        for (j = 8; j >= 0; j--)
        {
            for (i = 0; i < 9; i++)
            {
                if (i - 4 == bk1 || i - 4 == bk2) printf("X");
                else if (map[j][i] < 0) printf("o");
                else if (map[j][i] > 0) printf("*");
                else printf("-");
            }
            printf("
    ");
        }
        return 0;
    }
    



    -----------------------------------------

    -----------------------------------------

    -----------------------------------------

    -----------------------------------------

  • 相关阅读:
    Android将TAB选项卡放在屏幕底部(转)
    unix进程间通信
    C优先级顺序(转)
    C/C++ 内存补齐机制
    Android Sqlite ORM 工具
    类型安全性测试
    反射手册笔记 2.程序集,对象和类型
    CLR笔记:15.委托
    反射手册笔记 4.创建对象
    反射手册笔记 1.灵活的编程方法
  • 原文地址:https://www.cnblogs.com/cyendra/p/3681565.html
Copyright © 2011-2022 走看看