【dfs】简单游戏(jzoj 2121)
生活随笔
收集整理的這篇文章主要介紹了
【dfs】简单游戏(jzoj 2121)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
簡單游戲
題目大意
原本有n個數(shù)字,第1,2個相加,第2,3個相加……第n-1,n個相加,由此得出一個長度為n-1的新序列,然后不停重復(fù),最后得出一個t,現(xiàn)在給出一開始的n和t求符合的序列(字典序最小)(多組數(shù)據(jù),0 0結(jié)束)
樣例輸入
4 16
3 9
0 0
樣例輸出
3 1 2 4
1 3 2
對樣例解釋:
開始排列: 3 1 2 4
第一次操作:3+1=4 1+2=3 2+4=6
得到: 4 3 6
第二次得到: 7 9
最后就是: 16
數(shù)據(jù)范圍限制
數(shù)據(jù)保證有解。請注意加粗字體!
對于30%的數(shù)據(jù),保證該組里的每個N都不超過10。
對于100%的數(shù)據(jù),保證有每個N不超過20,且每組數(shù)據(jù)的個數(shù)不超過10。
解題思路
我們可以由題意得出下圖,圖中代表的是數(shù)字相加的次數(shù),可以看出,這是一個楊輝三角,我們可以先求出楊輝三角,再dfs枚舉每一個數(shù)
三個優(yōu)化(必打):
1:判斷當(dāng)前總值是否大于t,若大于,退出
2:因為楊輝三角有對稱的特性,所以判斷a[i]是否大于a[n-i+1],若不大于,退出
3:將剩下的數(shù)和楊輝三角剩下可乘的的數(shù)排列,將最大的乘最大的,最小的成最小的,得出剩下的數(shù)最大的結(jié)果,若當(dāng)前總值+最大的結(jié)果<t 那么絕對不可能有結(jié)果,就退出,然后將最大的乘最小的,最小的乘最大的,得出最小的結(jié)果,若當(dāng)前總值+最小的結(jié)果>t 那么絕對不可能有結(jié)果,就退出
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; int c[25],yh[25][25],p[25],s[25],h[25],n,t,dg; void dfs(int x,int y) {if (x>n&&y==t)//判斷是否達(dá)到結(jié)果{dg=1;//找到結(jié)果return;}if (x>n) return;//判斷是否越界if (y>=t) return;//判斷是否大于tint w=0,big=0,small=0;for (register int i=1;i<=n;i++)//沒選過的數(shù)if (!p[i]){s[++w]=i;//記錄h[w]=yh[n][x+w-1];//和他相配對的}sort(h+1,h+1+w);//排for (register int i=1,j=w;i<=w;i++,j--){small+=s[i]*h[j];//最小的big+=s[i]*h[i];//最大的}if (y+big<t) return;//剪枝if (y+small>t) return;for (register int i=1;i<=n;i++)if (!p[i]){if (x>n/2&&i<=c[n-x+1]) continue;//判斷是否大于相對稱的地方c[x]=i;//記錄p[i]=1;//記錄dfs(x+1,i*yh[n][x]+y);//dfsp[i]=0;if (dg) return;c[x]=0;} } int main() {yh[1][1]=1;for (register int i=2;i<=20;i++)for (register int j=1;j<=i;j++)yh[i][j]=yh[i-1][j-1]+yh[i-1][j];//楊輝三角scanf("%d %d",&n,&t);while(n||t){dg=0;memset(c,0,sizeof(c));//清除dfs(1,0);for (int i=1;i<=n;i++)printf("%d ",c[i]);printf("\n");scanf("%d %d",&n,&t);}return 0; }總結(jié)
以上是生活随笔為你收集整理的【dfs】简单游戏(jzoj 2121)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 语重心长的重是什么意思 语重心长中重的意
- 下一篇: 立冬的民俗活动 立冬吃什么好