hdu 2461

来源:互联网 发布:爱淘宝返利 编辑:程序博客网 时间:2024/06/05 20:15

做了差不多一天,终于过

题意:

就是给你NN<=20)个矩阵,共有M(M<=100000)个询问,每个询问就是涂r个矩阵,问总共有多少个单位矩阵被涂了。

开始时,其实就是一个容斥定理,总个数=所有的矩阵的面积重合两次的面积 +重合三次的面积。。。。。

我用想到的直接用dp[N][N]来求dp[i][j]表示i表示宽度,第j矩阵到第j+i矩阵的重合,打了一下代码,发现完全错误了,其实要求任意个矩阵的重合,不一定是连续的。想到这里,N十分小,而M十分大,就采用了状态压缩,每一矩阵用一位二进制表示总共有(1<<N)种状态。先预处理,将所有的情况都求出来。询问时,直接一个暴搜,将所有的组合求出来,分别记录在c数组中,c[i]表示i个矩阵重合的单位矩阵个数。

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>using namespace std;#define MIN(a,b) ((a)<(b)?(a):(b))#define N 21struct node{    int c,x1,x2,y1,y2;//c表示是否重合,1重合,0不重合}co[N],a[1<<N];int fa[1<<N],b[N];int f[N+10];int c[N];void in(){    f[0]=1;    for(int i=1;i<=20;i++) f[i]=f[i-1]*2;}int zhao(int &x,int &y,int x1,int y1,int x2,int y2){    if(x1>x2) swap(x1,x2),swap(y1,y2);    if(x2>=y1) return 0;    else    {        x=x2;        y=MIN(y1,y2);    }    return 1;}void find(int t,int i,int j){    int c1,c2;    c1=zhao(a[t].x1,a[t].x2,a[i].x1,a[i].x2,co[j].x1,co[j].x2);    c2=zhao(a[t].y1,a[t].y2,a[i].y1,a[i].y2,co[j].y1,co[j].y2);    a[t].c=c1&c2;    j=t;}void init(int n){    int i,j;    a[0].x1=a[0].y1=0;    a[0].x2=a[0].y2=1000;    a[0].c=1;    for(i=1;i<f[n];i++) a[i].c=0;    memset(fa,0,sizeof(fa));    for(i=0;i<f[n];i++)        if(a[i].c)        {            for(j=0;j<n;j++)                if((i&f[j])==0&&fa[i+f[j]]==0)                {                    fa[i+f[j]]=1;                    find(i+f[j],i,j);                }        }}void dfs(int temp,int x,int n,int num){    for(int i=x;i<n;i++)    {        int j=temp+f[b[i]];        if(a[j].c)        {            c[num]+=(a[j].x2-a[j].x1)*(a[j].y2-a[j].y1);            dfs(j,i+1,n,num+1);        }    }}int main(){    in();    int cases=1,n,m;    while(~scanf("%d%d",&n,&m)&&n+m)    {        int i,j,r,index;        for(i=0;i<n;i++)            scanf("%d%d%d%d",&co[i].x1,&co[i].y1,&co[i].x2,&co[i].y2);        init(n);//预处理,将所有的情况求出来        printf("Case %d:\n",cases++);        for(int k=1;k<=m;k++)        {            int sum=0;            scanf("%d",&r);            for(i=0;i<r;i++)            {                scanf("%d",&b[i]);                b[i]--;                sum+=(co[b[i]].x2-co[b[i]].x1)*(co[b[i]].y2-co[b[i]].y1);            }            memset(c,0,sizeof(c));            dfs(0,0,r,1);            int mul=-1;            for(i=2;i<=r;i++)            {                sum+=c[i]*mul;                mul*=-1;            }            printf("Query %d: %d\n",k,sum);        }        printf("\n");    }    return 0;}


原创粉丝点击