hdu6435 Problem J. CSGO标程讲解以及改正标程的一个错误(本来第一个样例过不了2333) 以及 poj2926 五维曼哈顿距离模板

比赛的时候抄poj2926的模板,但改不来啊orz

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int dem=5;        //维数
const int maxxn=100005;
const double inf=1e200;
struct Point{
    double x[dem];
}p[maxxn];
int n;
double minx[1<<dem], maxx[1<<dem];
 
double solve(){
    int i, j, k, t, tmp=1<<dem;
    double s, ans=-inf;
    for(i=0; i<tmp; i++){
        minx[i]=inf;
        maxx[i]=-inf;
    }
    for(i=0; i<n; i++){
        for(j=0; j<tmp; j++){
            t=j;s=0;
            for(k=0; k<dem; k++){
                if(t&1)
                s+=p[i].x[k];
                else s-=p[i].x[k];
                t>>=1;
            }
            if(maxx[j]<s)maxx[j]=s;
            if(minx[j]>s)minx[j]=s;
        }
    }
    for(i=0; i<tmp; i++){
        if(maxx[i]-minx[i]>ans)
        ans=maxx[i]-minx[i];
    }
    return ans;
}
int main(){
    //freopen("1.txt", "r", stdin);
    int i, j;
    while(scanf("%d", &n)!=EOF){
        for(i=0; i<n; i++){
            for(j=0; j<dem; j++)
                scanf("%lf", &p[i].x[j]);
        }
        printf("%.2f\n", solve());
    }
    return 0;
}
View Code

 

 后来看了标程,感觉上面那个算法是瞎搞的,于是改成了正确的姿势:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include<ctime>
using namespace std;
#define LL double

int T, n, m, K  ;
LL A[64], B[64], Ans,val,x[6];

int main()
{
    int i, k, S;


        K=5;
        cin>>n;
        Ans = 0;
        for (int i = 0; i < 64; i++)A[i] = B[i] = -1e200;

        for (i = 1; i <= n; i++)
        {

            for (k = 0; k<K; k++)
                scanf("%lf", &x[k]);
            for (S = 0; S<1 << K; S++)
            {
                LL Sum = 0;
                for (k = 0; k<K; k++)
                    Sum += x[k] * ((((S >> k) & 1) << 1) - 1);
                A[S] = max(A[S], Sum);
            }
        }


        for (S = 0; S<1 << K; S++)
            {Ans = max(Ans, A[S] + A[(1 << K) - 1 - S]);
            }
        printf("%.2lf\n", Ans);

}
/*
3
2 5 6 2 1.5
1.2 3 2 5 4
7 5 3 2 5

*/
View Code

这个程序的二进制操作比较秀,具体来说:

((((S >> k) & 1) << 1) - 1)这一句是if(S的第k位为1)f=1; else f=-1 的缩写(感觉反而更麻烦了233)

A[S] + A[(1 << K) - 1 - S]这一句的意思是把符号相反的一组最优向量加起来。因为(1 << K) - 1 - S与S的0,1 互补,对应向量里+、- 互补。

标程唯一被hack的地方是数组初始化时用了memset,应该全部赋值为-inf

下面给出标程(改了一句)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include<ctime>
using namespace std;
#define LL long long

int T, n, m, K, val, x[6];
LL A[64], B[64], Ans;

int main()
{
    int i, k, S;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d%d", &n, &m, &K);
        Ans = 0;
        //memset(A, 0, sizeof(A));
        //memset(B, 0, sizeof(B));
        for (int i = 0; i < 64; i++)A[i] = B[i] = -1e18;
        for (i = 1; i <= n; i++)
        {
            scanf("%d", &val);
            for (k = 0; k<K; k++)
                scanf("%d", &x[k]);
            for (S = 0; S<1 << K; S++)
            {
                LL Sum = val;
                for (k = 0; k<K; k++)
                    Sum += x[k] * ((((S >> k) & 1) << 1) - 1);
                A[S] = max(A[S], Sum);
            }
        }

        for (i = 1; i <= m; i++)
        {
            scanf("%d", &val);
            for (k = 0; k<K; k++)
                scanf("%d", &x[k]);
            for (S = 0; S<1 << K; S++)
            {
                LL Sum = val;
                for (k = 0; k<K; k++)
                    Sum += x[k] * ((((S >> k) & 1) << 1) - 1);
                B[S] = max(B[S], Sum);
            }
        }

        for (S = 0; S<1 << K; S++)
            Ans = max(Ans, A[S] + B[(1 << K) - 1 - S]);
        printf("%lld\n", Ans);
    }
}



/*
1
2 2 1
0 1
0 2
0 4
0 3

2
2 2 1
0 233
0 666
0 123
0 456
2 2 1
100 0 1000 100 1000 100
100 0

*/

 

posted @ 2018-08-22 16:48  SuuTTT  阅读(248)  评论(0编辑  收藏  举报