目录
1.康托展开
const int fac[]={1,1,2,6,24,120,720,5040,40320,362880,3628800};//阶乘0-10
int cantor(int a[],int n){//cantor展开,n表示是n位的全排列,a[]表示全排列的数(用数组表示)
int ans=0,sum=0;
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++)
if(a[j]<a[i])
sum++;
ans+=sum*fac[n-i];
sum=0;
}
return ans+1;
}
2.状态编号
我们可以用0,1,2,3分别表示指定格的上右下左
状态=((行号-1)*列数+(列号-1))*4+ 0/1/2/3
int numbers(int i,int j) { return (i-1)*m+j-1<<2; } 状态=number(x,y)+0/1/2/3
其实所有网格图中的状态都可以采取类似的方法
状态编号= 图中编号* S+ x ,x∈[0,S) S=每种编号状态数
3.树的直径
https://blog.csdn.net/westbrook1998/article/details/83246821
树形dp方法:(感觉更简洁)
namespace subtask2{
int dfs(int x,int fa){
int sum1=0,sum2=0;
for(int i=head[x],y;i;i=e[i].next){
y=e[i].to;
if(y==fa) continue;
sum2=max(sum2,dfs(y,x)+e[i].val);
if(sum2>sum1) swap(sum1,sum2);
}
ans=max(ans,sum1+sum2);
return sum1;
}
void solve(){
dfs(1,0);
printf("%d\n",ans);
return ;
}
}