charles和sunny在玩乙個簡單的遊戲。若給出1~n的乙個排列a,則將a1、a2相加,a2、a3相加……an-1、an相加,則得到一組n-1個元素的數列b;再將b1、b2相加,b2、b3相加,bn-2、bn-1相加,則得到一組n-2個元素的數列……如此往復,最終會得出乙個數t。而charles和sunny玩的遊戲便是,charles給出n和t,sunny在盡可能短的時間內,找到能通過上述操作得到t且字典序最小的1~n的排列。(sunny大聲說:「what an easy game!」,接著幾下就給出了解),charles覺得沒意思,就想和你玩,當然,你可以用一種叫做「電子計算機」的東西幫你。
本題有多組資料,對於每組資料:一行兩個整數n(0< n<=20),t即最後求出來的數。兩個0表示輸入結束。
對於每組測試資料輸出一行n個整數,用空格分開,行尾無多餘空格,表示求出來的滿足要求的1~n的乙個排列。
4 16
3 90 0
3 1 2 4
1 3 2
對於30%的資料,保證該組裡的每個n都不超過10。
對於100%的資料,保證有每個n不超過20,且每組資料的個數不超過10。
可以通過觀察發現,t是由這個n的排列的每個數乘上乙個係數得到,係數是楊輝三角第n行。
若直接dfs,就會超時,所以需要剪枝。
1.若已經找到答案,結束dfs
2.若當前的和加上後面能算出的最大值仍小於t,返回上層。
3.若當前的和加上後面能算出的最小值仍大於t,返回上層。
4.由於係數對稱,而要找字典序最小的序列,所以,當係數相同時,小的數一定在前面。
#include
#include
#include
#include
#include
using namespace std;
#define n 25
int f[n][n];
intq[n],t[n],x[n];
int n,m;
bool b;
void pre()
bool comp(int
x,int
y)bool pd(int dep,int
s) //printf("max=%d\n",an);
if (anan=s;
j=0;
for (int i=1;i<=n;++i)
if (t[i]==0)
//printf("min=%d\n",an);
if (an>m) return true;
return false;
}void dfs(int dep,int
s) return;
}if (s>m) return;
if (pd(dep+1,s)) return;
if (dep>n/2 && q[dep]
for (int i=1;i<=n;++i)
if (t[i]==0)
}int main()
return
0;}
JZOJ 數字遊戲 DP
小w發明了乙個遊戲,他在黑板上寫出了一行數字a1,a2,a3,an,然後給你m個回合的機會,每回合你可以從中選擇乙個數字擦去它,接著剩下來的每個數字ai都要遞減乙個值bi,即a1減掉b1,a2減掉b2,如此重複m個回合,所有你擦去的數字之和就是你所得的分數。小w和他的好朋友小y玩了這個遊戲,可是他發...
Jzoj 2032 數字遊戲
按某種順序在紙上寫下1 n 1 n 10 1 n 1 n 10 1 n 1 n 1 0 之間的所有數,然後把相鄰的數字相加,得到乙個比原數列少一項的數列。對新數列重複上述的操作,直到整個數列只剩乙個數為止。n 4 n 4n 4的時候,整個遊戲的流程可能如下所示 3 1 2 4 4 3 6 7 9 1...
jzoj數字遊戲 貪心 DP
description 一行數字a1,a2,a3,an,有m個回合,每個回合必須從中選擇乙個數字擦去它,接著每個回合後剩下來的每個數字ai都要遞減乙個相應的值bi。如此重複m個回合,所有你擦去的數字之和就是你所得的分數。給出n,m,a數列和b數列,求所得的最多的分數。input 輸入檔案的第一行是乙...