dfs剪枝:洛谷P2809 hzwer爱折纸
生活随笔
收集整理的這篇文章主要介紹了
dfs剪枝:洛谷P2809 hzwer爱折纸
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
傳送門
解析
dfs暴力枚舉即可
這題的重點(diǎn)是如何剪枝
不難發(fā)現(xiàn),隨著不斷處理,紙條只會(huì)越來越短,且所有數(shù)字總加和不變
我一開始想到了2個(gè)條件:
1.當(dāng)前長度比理想紙條小,return;
2.總加和與理想紙條不等,直接輸出N
但是這樣仍是O(n!)的級(jí)別,得到了80分
后來又想到:
反轉(zhuǎn)之后對(duì)后一半的與反轉(zhuǎn)前對(duì)前一半的折疊是等效的,所以只需要遞歸一半的長度即可
從而通過本題
代碼
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <string> #include <queue> #include <string> #include<map> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)); using namespace std; const int N=50; const int M=1e9; int n,m,mod; int a[N],b[N]; int save[N][N],save2[N][N]; int flag; void memory(int l){for(int i=0;i<=a[0];i++) save[l][i]=a[i]; } void restore(int l){for(int i=0;i<=save[l][0];i++) a[i]=save[l][i]; } void fold(int p){memory(a[0]);int x=0,l=a[0];if(p<=a[0]/2){for(int i=save[l][0];i>=p+p+1;i--) a[++x]=save[l][i];for(int i=1;i<=p;i++) a[++x]=save[l][i]+save[l][p+p-i+1];a[0]-=p;}else{for(int i=1;i<=2*p-a[0];i++) a[++x]=save[l][i];for(int i=2*p-save[l][0]+1;i<=p;i++) a[++x]=save[l][i]+save[l][save[l][0]-(i-(2*p-save[l][0]))+1];a[0]-=(a[0]-p);}return; } void memory2(int l){for(int i=0;i<=a[0];i++) save2[l][i]=a[i]; } void restore2(int l){for(int i=0;i<=save2[l][0];i++) a[i]=save2[l][i]; } void fanzhuan(){memory2(a[0]);for(int i=1;i<=a[0];i++) a[i]=save2[a[0]][save2[a[0]][0]-i+1]; } bool judge(){for(int i=0;i<=b[0];i++){if(a[i]!=b[i]) return false;}return true; } void print(){for(int i=1;i<=a[0];i++) printf("%d ",a[i]);printf("\n"); } bool jd(){int pd[N]={},ok[N]={};for(int i=1;i<=a[0];i++) pd[i]=a[i];sort(pd+1,pd+1+a[0]);for(int i=1;i<=b[0];i++) ok[i]=b[i];sort(ok+1,ok+1+b[0]); // for(int i=1;i<=b[0];i++){ // printf("b=%d a=%d\n",ok[i],pd[i]); // }for(int i=1;i<=b[0];i++){if(ok[i]<pd[i]) return false;}return true; } void dfs(){ // print();if(flag) return;if(a[0]<b[0]) return; // if(!jd()) return;int l=a[0];if(a[0]==b[0]){if(judge()){printf("S\n");flag=1;return;}fanzhuan();if(judge()){printf("S\n");flag=1;}restore2(l);return;}for(int i=1;i<=a[0]/2;i++){fold(i);dfs();if(flag) return;restore(l);}fanzhuan();for(int i=1;i<=a[0]/2;i++){fold(i);dfs();if(flag) return;restore(l);}restore2(l);return; } int main(){while(scanf("%d",&n)==1){flag=0;int tot=0;mem(a,0);mem(b,0);for(int i=1;i<=n;i++) mem(save[i],0);for(int i=1;i<=n;i++){scanf("%d",&a[i]);tot+=a[i];}a[0]=n;scanf("%d",&m);for(int i=1;i<=m;i++){scanf("%d",&b[i]);tot-=b[i];}b[0]=m;if(m>n||tot!=0){printf("N\n");continue;}dfs();if(!flag) printf("N\n");}return 0; }總結(jié)
以上是生活随笔為你收集整理的dfs剪枝:洛谷P2809 hzwer爱折纸的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拿到一台新的电脑拿到新电脑的第一件事是什
- 下一篇: 路由器重置密码怎么设置路由器密码忘记怎么