bzoj4806~bzoj4809 象棋四连发 DP-高精度-匈牙利算法-dfs

Posted karl07

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4806~bzoj4809 象棋四连发 DP-高精度-匈牙利算法-dfs相关的知识,希望对你有一定的参考价值。

都是经典题了吧。。我好无聊。。

4806

4806-1801是双倍经验。。DP方程看代码吧。。

 1 /* http://www.cnblogs.com/karl07/ */
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 
 9 #define ll long long 
10 //#define P 9999973 //bzoj1801
11 #define P 999983 //bzoj4806
12 #define C(x) ((x)*(x-1)/2)
13 int n,m;
14 ll f[105][105][105];
15 
16 int main(){
17     scanf("%d%d",&n,&m);
18     f[0][0][0]=1;
19     for (int i=1;i<=n;i++){
20         for (int j=0;j<=m;j++){
21             for (int k=0;k<=m-j;k++){
22                 f[i][j][k]+=f[i-1][j][k];
23                 if (j>=1)          f[i][j][k]+=f[i-1][j-1][k]*(m-j-k+1);
24                 if (k>=1 && j<=m-1)f[i][j][k]+=f[i-1][j+1][k-1]*(j+1);
25                 if (j>=2)          f[i][j][k]+=f[i-1][j-2][k]*C(m-j-k+2);
26                 if (k>=2 && j<=m-2)f[i][j][k]+=f[i-1][j+2][k-2]*C(j+2);
27                 if (j>=1 && k>=1)  f[i][j][k]+=f[i-1][j][k-1]*j*(m-j-k+1);
28                 f[i][j][k]%=P;
29             }
30         }
31     }
32     ll ans=0;
33     for (int i=0;i<=m;i++){
34         for (int j=0;j<=m-i;j++){
35             ans+=f[n][i][j];
36             ans%=P;
37         }
38     }
39     printf("%lld\\n",ans);
40     return 0;
41 }

4807

就是 max(m,n) C min (m,n) 

 1 /* http://www.cnblogs.com/karl07/ */
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 struct INT {
 9     int b,a[60];
10     INT (){b=0; for (int i=0;i<=50;i++) a[i]=0;}
11 };
12 int A,B,c,n,m;
13 int P[1000005],p[1000005],cnt[1000005],ip[1000005];
14 INT Int(int x){
15     INT a;
16     for (a.b=0 ; x ; a.a[++a.b]=x%10,x/=10);
17     return a;
18 }
19 
20 INT operator * (const INT &x,const INT &y){
21     INT a;
22     a.b=min(50,x.b+y.b-1);
23     for (int i=1;i<=x.b;i++) for (int j=1;j<=y.b;j++) if (i+j-1<=50) a.a[i+j-1]+=x.a[i]*y.a[j]; 
24     for (int i=1;i<=a.b;a.b+=(i==a.b && a.a[i+1] && i+1<=50),i++)  a.a[i+1]+=a.a[i]/10,a.a[i]%=10;
25     for (;a.a[a.b]==0 && a.b!=1; a.b--);
26     return a;
27 }
28 
29 void print_INT(INT x){
30     for (int i=min(x.b,50);i>=1;i--) printf("%d",x.a[i]); 
31     puts("");
32 }
33 
34 void Prime(int n){
35     for (int i=2;i<=n;i++){
36         if (!P[i]){
37             p[++c]=i,ip[i]=c;
38             for (int j=i+i;j<=n;j+=i) P[j]=1;
39         }
40     }
41 }
42 
43 void pt(int x) {
44     printf("%d\\n",x);
45 }
46 
47 void fac(int x,int y){
48     for (int i=1;i<=c && P[x];i++) while (!(x%p[i])) x/=p[i],cnt[i]+=y;
49     cnt[ip[x]]+=y;
50 }
51 
52 INT ans=Int(1);
53 int main(){
54     scanf("%d%d",&A,&B);
55     n=max(A,B),m=max(max(A,B)-min(A,B),min(A,B));
56     Prime(n);
57     for (int i=m+1;i<=n;i++) fac(i,1);
58     for (int i=2;i<=n-m;i++) fac(i,-1);
59     for (int i=1;i<=c;i++) while (cnt[i]--) ans=ans*Int(p[i]);
60     print_INT(ans);
61     return 0;
62 }

4808

黑白染色然后匈牙利

 1 /* http://www.cnblogs.com/karl07/ */
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 
 9 struct edge{
10     int next,to;
11 }e[1000005];
12 int ade,n,m,cnt,T,c;
13 int x[]={1,2,-1,-2,-1,2,1,-2};
14 int y[]={2,1,-2,-1,2,-1,-2,1};
15 int mp[205][205],id[205][205],first[1000005],vis[1000005],match[1000005];
16 
17 void addedge(int x,int y){
18     e[++ade].next=first[x];
19     e[ade].to=y;
20     first[x]=ade;
21 }
22 
23 bool check(int x,int y){
24     return (x>=1 && x<=n && y>=1 && y<=m && !mp[x][y]);
25 }
26 
27 #define s e[x].to
28 bool hungary(int p){
29     for (int x=first[p];x;x=e[x].next){
30         if (vis[s]!=T){
31             vis[s]=T;
32             if (!match[s] || hungary(match[s])) {match[s]=p; return 1;}
33         }
34     }
35     return 0;
36 }
37 #undef s
38 
39 int main(){
40     scanf("%d%d",&n,&m);
41     for (int i=1;i<=n;i++){
42         for (int j=1;j<=m;j++){
43             scanf("%d",&mp[i][j]);
44             cnt+=(!mp[i][j]);
45             id[i][j]=++c;
46         }
47     }
48     for (int i=1;i<=n;i++)
49         for (int j=1;j<=m;j++)
50             if (((i+j)&1) && !mp[i][j])for (int k=0;k<8;k++) if (check(i+x[k],j+y[k])) addedge(id[i][j],id[i+x[k]][j+y[k]]);
51     for (int i=1;i<=n;i++){
52         for (int j=1;j<=m;j++){
53             if (!mp[i][j] && ((i+j)&1)){
54                 T=id[i][j];
55                 cnt-=hungary(T);
56             }
57         }
58     }
59     printf("%d\\n",cnt);
60     return 0;
61 }

4809

直接dfs

 1 /* http://www.cnblogs.com/karl07/ */
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 
 9 int n,ans;
10 int ban[20][20],y[20],a[40],b[40];
11 
12 void dfs(int i){
13     if (i>n) {ans++; return;} 
14     for(int j=1;j<=n;j++) if (!(ban[i][j] || y[j] || a[i+j-1] || b[n-i+j] )){
15         y[j]=a[i+j-1]=b[n-i+j]=1;
16         dfs(i+1);
17         y[j]=a[i+j-1]=b[n-i+j]=0;        
18     }
19 }
20 
21 int main(){
22     scanf("%d",&n);
23     for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%d",&ban[i][j]);
24     dfs(1);
25     printf("%d\\n",ans);
26     return 0;
27 }
皇后

 

以上是关于bzoj4806~bzoj4809 象棋四连发 DP-高精度-匈牙利算法-dfs的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj 4809]皇后 (dfs)

bzoj4809 -- 组合数

bzoj4806 炮

bzoj 4806: 炮dp

BZOJ 4806 : 炮

BZOJ 1801 中国象棋