zoukankan      html  css  js  c++  java
  • 叉姐的魔法训练(第二课)---- 冰系魔法入门

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

    一 矩阵相乘

    POJ 3213 PM 3

    给出三个矩阵A(NP)、B(PM)、C(NM) N,P,M<1000

    C=A*B,但是矩阵C中有可能有一个元素的值是错误的。

    问哪一个元素是错的,并求出正确的值。

    直接暴力求出C的话O(n^3)必然会超时

    注意矩阵乘法的公式


    用sumB[i]表示矩阵B第i行所有元素的和,sumC[i]表示矩阵C第i行所有元素的和。

    则 sumC[i] = ∑ A[i][k]*sumB[k] ,若理论值与计算值不等,则说明矩阵C第i行的元素出错。

    接下来只要枚举计算矩阵C第i行的每个元素找到错解即可。

    总复杂度仅有O(n^2)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    typedef long long LL;
    const int maxn=1011;
    
    int N,P,M;
    int A[maxn][maxn],B[maxn][maxn];
    LL C[maxn][maxn];
    LL sumB[maxn],sumC[maxn];
    int wr,wl;
    LL rt;
    int main()
    {
        while (~scanf("%d%d%d",&N,&P,&M)){
            for (int i=1;i<=N;i++){
                for (int j=1;j<=P;j++){
                    scanf("%d",&A[i][j]);
                }
            }
            memset(sumB,0,sizeof(sumB));
            for (int i=1;i<=P;i++){
                for (int j=1;j<=M;j++){
                    scanf("%d",&B[i][j]);
                    sumB[i]+=B[i][j];
                }
            }
            memset(sumC,0,sizeof(sumC));
            for (int i=1;i<=N;i++){
                for (int j=1;j<=M;j++){
                    scanf("%I64d",&C[i][j]);
                    sumC[i]+=C[i][j];
                }
            }
            //puts("Done.");
            wr=-1;
            for (int i=1;i<=N;i++){
                LL sum=0;
                for (int j=1;j<=P;j++){
                    sum+=A[i][j]*sumB[j];
                }
                if (sum!=sumC[i]){
                    wr=i;
                    break;
                }
            }
            if (wr==-1) puts("Yes");
            else{
                puts("No");
                for (int i=1;i<=M;i++){
                    LL sum=0;
                    for (int j=1;j<=P;j++){
                        sum+=A[wr][j]*B[j][i];
                    }
                    if (sum!=C[wr][i]){
                        wl=i;
                        rt=sum;
                        break;
                    }
                }
                printf("%d %d
    ",wr,wl);
                printf("%I64d
    ",rt);
            }
        }
        return 0;
    }
    

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

    二 时光倒流

    POJ 3465 Battle

    与敌人战斗n回合,每回合对敌人造成x点伤害,或防御敌人所有伤害,或恢复y点生命。自身生命值为H1,敌人生命值为H2。

    生命小于等于0则死亡,n回合后也会死亡。若能赢,输出最小回合数。若必输,输出最大伤害数。

    只要不会死,每回合都贪心攻击。若生命减为0以下,则改写过去某一回合,要求恢复最多的生命,用优先队列维护。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    
    using namespace std;
    const int maxn=211111;
    int n,x,y,h1,h2;
    int a[maxn];
    priority_queue<int>que;
    int main()
    {
        while (~scanf("%d%d%d%d%d",&n,&x,&y,&h1,&h2)){
            while (!que.empty()) que.pop();
            for (int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            int i,hit=0,mhit=0;
            for (i=1;i<=n;i++){
                hit++;
                mhit=max(hit,mhit);
                if (hit*x>=h2) break;
                h1-=a[i];
                que.push(max(a[i],y));
                while (!que.empty()&&h1<=0){
                    int up=que.top();
                    que.pop();
                    h1+=up;
                    hit--;
                }
            }
            if (i<=n){
                printf("Win
    %d
    ",i);
            }
            else{
                printf("Lose
    %d
    ",mhit*x);
            }
        }
        return 0;
    }
    

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

    三 凸包本质

    POJ 2595 Min-Max

    //题意与题解:

    题意:设函数F(x1,x2...xn)=Σuixi(1<=i<=n),u为函数固定的系数,且对u有限制Σu=1且u∈[0,1],但是你不知道,你只知道一组输入x1,x2...xn对应的输出为C,问题是给定的另一组输入y1,y2...yn的输出最小与最大可能是多少。(冰封寒月)
    观察一下u的神奇范围我们可以很直观的联想到一群质点的重心公式,不妨将(xi,yi)作为坐标放在平面直角坐标系中,我们就可以将所有的有序实数对看成质量相等的质点,C就是其重心的x坐标,答案即为重心的y坐标,由重心知识可知重心位于点集的凸包内部,所以贪心得到答案为凸包边(点)上,所以求出凸包维护一下答案就行了。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    const int maxn=61111;
    const double OO=1e50;
    struct Point{
        int x,y;
        void output(){
            printf("%d %d
    ",x,y);
        }
    }p[maxn];
    int n;
    Point MinA;
    Point stack[maxn];
    int top;
    double cross(Point A,Point B,Point C){
        return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
    }
    double dist(Point A,Point B){
        return hypot(A.x-B.x,A.y-B.y);
    }
    bool cmp(Point A,Point B)
    {
        double k=cross(MinA,A,B);
        if(k<0) return 0;
        if(k>0) return 1;
        return dist(MinA,A)<dist(MinA,B);
    }
    
    void Graham(Point p[],int n)
    {
        for(int i=1;i<n;i++)
            if(p[i].y<p[0].y||(p[i].y==p[0].y&&p[i].x<p[0].x))
                swap(p[i],p[0]);
        MinA=p[0];
        p[n]=p[0];
        sort(p+1,p+n,cmp);
        stack[0]=p[0];
        stack[1]=p[1];
        top=2;
        for(int i=2;i<n;i++){
            while(top>=2&&cross(stack[top-2],stack[top-1],p[i])<=0) top--;
            stack[top++]=p[i];
        }
    }
    int c;
    double minn,maxx;
    void check(Point a,Point b){
        if (a.x>b.x) swap(a,b);
        if (a.x<=c&&b.x>=c){
            if (a.x==c&&b.x==c){
                maxx=max(maxx,(double)max(a.y,b.y));
                minn=min(minn,(double)min(a.y,b.y));
            }
            else{
                double k=((double)c-a.x)/((double)b.x-a.x)*(b.y-a.y)+a.y;
                maxx=max(maxx,k);
                minn=min(minn,k);
            }
        }
    }
    
    int main()
    {
        while (~scanf("%d%d",&n,&c)){
            for (int i=0;i<n;i++) scanf("%d",&p[i].x);
            for (int i=0;i<n;i++) scanf("%d",&p[i].y);
            if (n==1){
                printf("%0.3f %0.3f
    ",(double)p[0].y,(double)p[0].y);
                continue;
            }
            Graham(p,n);
            minn=OO,maxx=-OO;
            //for (int i=0;i<top;i++) stack[i].output();
            stack[top]=stack[0];
            for (int i=1;i<=top;i++){
                check(stack[i-1],stack[i]);
            }
            printf("%0.3f %0.3f
    ",minn,maxx);
        }
        return 0;
    }


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

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


  • 相关阅读:
    阻止表单重复提交的办法以及支付成功后页面后退重复提交的解决方案
    jsp页面的共用
    空间谱专题02:波束形成(Beamforming)
    空间谱专题01:信号模型
    空间谱专题00:综述
    BP神经网络
    fdatool的滤波器设计
    Testbench
    Cordic算法简介
    快速删除注释
  • 原文地址:https://www.cnblogs.com/cyendra/p/3681566.html
Copyright © 2011-2022 走看看