Google Kickstart round G 2018(状压搜索)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oidoidoid/article/details/87014830

A

输出满足条件的三元组的个数

特殊考虑0和1

WA2

细节写的太丑了

#include<iostream>
#include<string.h>
#include<algorithm>
#define N 10005
using namespace std;
long long a[N];
long long sum[200005];
int main(){
    int T,ca=0;
    scanf("%d",&T);
    while (T--){
        ca++;
        memset(sum,0,sizeof(sum));
        int n;
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            sum[a[i]]++;
        }
        long long  ans=0;
        sort(a+1,a+1+n);
        long long tot1=0,tot0=0;
        a[n+1]=2;
        for (int i=1;i<=n+1;i++) if (a[i]!=0){ tot0=i-1;break; }
        if (tot0>=3) ans+=(tot0*(tot0-1)*(tot0-2)/6);
        for (int i=tot0+1;i<=n+1;i++) if (a[i]!=1){ tot1=i-1-tot0;break; }
        if (tot1>=3) ans+=(tot1*(tot1-1)*(tot1-2)/6);
        for (int i=1;i<=200000;i++){
        	if (i!=1&&sum[i]>1) ans+=(tot1*sum[i]*(sum[i]-1)/2);
        	if (tot0>1) ans+=(tot0*(tot0-1)/2*sum[i]);
		}
        for (int i=tot0+tot1+1;i<=n;i++){
            for (int j=i+1;j<=n;j++){
                if (a[i]*a[j]<=200000){
					ans+=sum[a[i]*a[j]];
				} 
            }
        }
        printf("Case #%d: %lld\n",ca,ans);
    }
    return 0;
}

B

似乎是离散化线段树离线回答

懒得套板子了……

C

状压搜索

NM*2^Ct预处理:

1.接下来可达的状态

2.当前状态能量和

3.是否可以直接回到EXIT推出

很妙

最后的搜索没加记忆化会T

#include<iostream>
#include<string.h>
using namespace std;

long long v[105][105],tp[20][2];
int mk[105][105];
long long tot,etot;
long long e[1<<16], nxt[1<<16];
bool ext[1<<16],vis[105][105];
long long f[1<<16];
int ex, ey, sx,sy,n,m;
int dir[4][2]={0,1,0,-1,1,0,-1,0};

void pre(int nx, int ny, int now){
    for (int i=0;i<4;i++){
        int x=nx+dir[i][0];
        int y=ny+dir[i][1];
        if (x==ex&&y==ey) ext[now]=true;
        if (x>0&&x<=n&&y>0&&y<=m&&!vis[x][y]&&v[x][y]!=-100000){
            vis[x][y]=true;
            if (v[x][y]>=0){
                e[now]+=v[x][y];
                pre(x,y,now);
            }
            else{
                if (now&(1<<(mk[x][y]-1))){
                    e[now]+=v[x][y];
                    pre(x,y,now);
                }
                else{
                    nxt[now]|=(1<<(mk[x][y]-1));
                }
            }
        }
    }
}

long long dfs(int now){
	if (f[now]!=-2) return f[now];
    long long res=-1;
    if (ext[now]) res=e[now];
    for (int i=1;i<=tot;i++){
        if( (nxt[now]&(1<<(i-1)))&&v[tp[i][0]][tp[i][1]]+e[now]>=0){
            res=max(res,dfs(now|(1<<(i-1))));
        }
    }
    return f[now]=res; 
}

int main(){
    int T;
    scanf("%d",&T);
    long long  E;
    int ca=0;
    while (T--){
    	memset(nxt,0,sizeof(nxt));
    	memset(ext,0,sizeof(ext));
    	ca++;
        tot=0;
        scanf("%d%d%lld%d%d%d%d",&n,&m,&E,&sx,&sy,&ex,&ey);
        for (int i=1;i<=n;i++){
            for (int j=1;j<=m;j++){
                scanf("%lld",&v[i][j]);
                if (v[i][j]<0&&v[i][j]!=-100000){
                    tot++;
                    mk[i][j]=tot;
                    tp[tot][0]=i;
                    tp[tot][1]=j;
                }
            }
        }
        for (int i=0;i<=(1<<tot)-1;i++){
            e[i]=E;
            for (int j=1;j<=n;j++){
            	for (int k=1;k<=m;k++) vis[j][k]=false;
			}
            pre(sx,sy,i);
        }
        for (int i=0;i<=(1<<tot)-1;i++)  f[i]=-2;
        long long ans=max(-1LL,dfs(0));
        printf("Case #%d: %lld\n", ca,ans);
    }
}

猜你喜欢

转载自blog.csdn.net/oidoidoid/article/details/87014830