带点组合的东西吧
黑书P257 其实我没看懂它写的嘛玩意儿
这题还是挺不错的 一个模糊的思路可能会好想一些 就是大体的递推方程 dp1[][]表示降序 dp2[][]表示升序 数组的含义为长度为i的第一个数为j且相对第一个数为升或降的排列数 当然j肯定要小于等于i的
dp1[i][j] = dp1[i][j]+dp2[i-1][k](k》=1&&k<j)
同理 dp2[i][j] = dp2[i][j]+dp1[i-1][k](k>=j&&k<i) 这里是因为dp2[i][j]中的j取不到i(因为后面还要升,就肯定取不到i);
这样任务完成了一半了 一定要深刻理解两个dp数组的含义 不然后半部分没法做
对于确定每一位的长度值 需要一步步的确定 先确定第一位的值 那就是挨个减dp1[n][1]dp2[n][1]..减到小于0时就确定了第一位的值 标记上 同时也确定了整体是升序还是降序 抛开第一位 同样的方式去确定第二位 这里要想清楚一点 因为dp数组里对于长度为i的j都不会大于i 你要找的那个数并不是dp里面的j而是相对第j个没有被标记的数 当然如果是升序 还得大于前一个数 降序还得小于前一个数
不知道为嘛一直TLE 在循环内随便加了个break条件就A了 好神奇~
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<queue> 7 #include<vector> 8 #define LL __int64 9 using namespace std; 10 LL dp1[22][22],dp2[22][22]; 11 int pa[22]; 12 bool f[22]; 13 int judge(int x) 14 { 15 int i,t=0; 16 for(i = 1; i <= 20 ; i++) 17 { 18 if(!f[i]) t++; 19 if(t==x) 20 { 21 f[i] = 1; 22 return i; 23 } 24 } 25 } 26 int main() 27 { 28 int i,j,g,n,k; 29 LL c; 30 scanf("%d",&k); 31 while(k--) 32 { 33 memset(dp1,0,sizeof(dp1)); 34 memset(dp2,0,sizeof(dp2)); 35 memset(f,0,sizeof(f)); 36 scanf("%d%I64d",&n,&c); 37 dp1[1][1] = dp2[1][1] = 1; 38 int tt=0; 39 for(i = 2; i <= n ; i++) 40 { 41 for(j = 1; j <= n ; j++) 42 { 43 for(g = 1; g < j ; g++) 44 dp1[i][j]+=dp2[i-1][g]; 45 for(g = j ; g < i ; g++) 46 dp2[i][j]+=dp1[i-1][g]; 47 } 48 } 49 LL ss=0; 50 int o=1,ff; 51 for(i = 1;i <= n ; i++) 52 { 53 c-=dp1[n][i]; 54 if(c>0) 55 { 56 c-=dp2[n][i]; 57 ff = 2; 58 } 59 else 60 { 61 ff=1; 62 } 63 if(c<=0) 64 { 65 pa[1] = i; 66 f[i] = 1; 67 if(ff==2) 68 c+=dp2[n][i]; 69 else 70 c+=dp1[n][i]; 71 int y = n-1; 72 while(1) 73 { 74 tt++; 75 if(tt>1000) 76 break; 77 int num=0; 78 for(i = 1 ; i <= 20 ; i++) 79 { 80 if(i==pa[o]) 81 break; 82 if(!f[i]) num++; 83 } 84 if(ff==2) 85 { 86 for(i = num+1; i <= y ; i++) 87 { 88 c-=dp1[y][i]; 89 if(o==n-1&&c==0) 90 { 91 pa[++o] = judge(i); 92 break; 93 } 94 if(c<=0) 95 { 96 c+=dp1[y][i]; 97 y--; 98 pa[++o] = judge(i); 99 ff = 1; 100 break; 101 } 102 } 103 } 104 else 105 { 106 107 for(i = 1 ; i <= num ; i++) 108 { 109 c-=dp2[y][i]; 110 if(o==n-1&&c==0) 111 { 112 pa[++o] = judge(i); 113 break; 114 } 115 if(c<=0) 116 { 117 c+=dp2[y][i]; 118 y--; 119 ff = 2; 120 pa[++o] = judge(i); 121 break; 122 } 123 } 124 } 125 if(c==0) 126 break; 127 } 128 break; 129 } 130 } 131 for(i = 1 ; i < n ; i++) 132 printf("%d ",pa[i]); 133 printf("%d ",pa[n]); 134 } 135 return 0; 136 }