日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

dfs剪枝:洛谷P2809 hzwer爱折纸

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 dfs剪枝:洛谷P2809 hzwer爱折纸 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

傳送門

解析

dfs暴力枚舉即可
這題的重點是如何剪枝
不難發現,隨著不斷處理,紙條只會越來越短,且所有數字總加和不變
我一開始想到了2個條件:
1.當前長度比理想紙條小,return;
2.總加和與理想紙條不等,直接輸出N
但是這樣仍是O(n!)的級別,得到了80分
后來又想到:
反轉之后對后一半的與反轉前對前一半的折疊是等效的,所以只需要遞歸一半的長度即可
從而通過本題

代碼

#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; }

總結

以上是生活随笔為你收集整理的dfs剪枝:洛谷P2809 hzwer爱折纸的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。