poj 1069 dfs(难在建立一个坐标)

来源:互联网 发布:encore制谱软件 编辑:程序博客网 时间:2024/05/20 14:43

<span style="color:#009900;">/*题意:就是给你1到25边长大小的三角形  你可以无限使用 问能不能构成一个大小为<=10的正六边形*//*思路:首先是坐标的变换 坐标变换好了 就是一样的做了  因为呈现的是60的角度 我想都学过坐标转换 由于是成60度的角 所以我们可以把这个放在图上表示为 一个小三角形表示为一个点 坐标的建立如上图所示*/</span>#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<vector>using namespace std;typedef long long ll;typedef pair<int,int> pp;#define inf 0x3f3f3f3f#define eps 1e-10#define maxl 100#define mem(i,j) memset(i,j,sizeof(i))const int mod=1e9+7;int p[maxl][maxl];int e,len[maxl],vis[maxl];vector<int> v;void init(){//对照图的话就很好初始化坐标了    memset(p,0,sizeof(p));    for(int i=1;i<=e;i++)        for(int j=1;j<=2*e+2*i-1;j++)        p[i][j]=1;    for(int i=e+1;i<=2*e;i++)        for(int j=2*(i-e);j<=4*e;j++)        p[i][j]=1;}bool ok(){    for(int i=0;i<v.size();i++){        if(e%v[i]==0) return true;    }    return false;}bool judge(int x,int y,int z){    if(x+z-1>2*e||y+2*z-2>4*e) return false; //这一步剪枝需要画图实践    if(y%2){        for(int i=0;i<z;i++)            for(int j=0;j<2*i+1;j++)//一定要注意  这里找了半天bug发现2*i+1 写成了2*i-1                if(!p[x+i][y+j]) return false;    }    else{        for(int i=0;i<z;i++)            for(int j=2*i;j<2*z-1;j++)                if(!p[x+i][y+j]) return false;    }    return true;}void turn(int x,int y,int z){//翻转    if(y%2){        for(int i=0;i<z;i++)            for(int j=0;j<2*i+1;j++)                p[x+i][y+j]=0;    }    else{        for(int i=0;i<z;i++)            for(int j=2*i;j<2*z-1;j++)                p[x+i][y+j]=0;    }}void turnagain(int x,int y,int z){//翻回来    if(y%2){        for(int i=0;i<z;i++)            for(int j=0;j<2*i+1;j++)                p[x+i][y+j]=1;    }    else{        for(int i=0;i<z;i++)            for(int j=2*i;j<2*z-1;j++)                p[x+i][y+j]=1;    }}bool dfs(int i,int j){    if(i>2*e) return true;    if(j>4*e) return dfs(i+1,1);//因为这里是从1开始的  所以下面要检查一下    if(!p[i][j])        int k;        for(k=j+1;k<=4*e;k++){            if(p[i][k]) break;        }        return dfs(i,k);    }    for(int k=0;k<v.size();k++){        if(judge(i,j,v[k])){            turn(i,j,v[k]);            if(dfs(i,j+1)) return true;            turnagain(i,j,v[k]);        }        else break;//这里神奇的剪枝 大的肯定放不下了    }    return false;}int main(){    freopen("in.txt", "r", stdin);    int t;    cin>>t;    while(t--){        int num;        cin>>e>>num;        for(int j=0;j<num;j++) cin>>len[j];        sort(len,len+num);        memset(vis,0,sizeof(vis));        v.clear();        for(int j=0;j<num;j++){            for(int k=j+1;k<num;k++){                if(!vis[k]&&len[k]%len[j]==0) vis[k]=1;            }        }        for(int j=0;j<num;j++) if(!vis[j]){v.push_back(len[j]);}//去重        if(ok()){cout<<"YES"<<endl;continue;}//剪枝        init();        if(dfs(1,1)) cout<<"YES"<<endl;        else cout<<"NO"<<endl;    }}

0 0