• 【YBTOJ】国际象棋


    题目链接:

    题目

    题目大意:

    给你边长分别为 (n,m) 的两个棋盘,将它们拼在一起,但是两个棋盘横纵各间隔 (w,h)。然后在这个畸形棋盘放 (k) 个互不能相吃的车,求方案数。

    正文:

    先考虑 (n=m,h=0)(或 (w=0))的情况。因为车的攻击是一整行和一整列,那么我们逐行判断可以选择哪一个格子,这样就可以保证一列里没有重的。对于每一行我们的放置方法也自然是可以直接考虑的。设 (f_{i,j}) 表示 (1)(i) 行已经放了 (j) 个车的方案数。则有转移方程 (f_{i,j}=f{i-1,j-1} imes(n-j+1)),其中 (n-j+1) 就表示了当前一行还能放车的位置的个数。通过这个方法完美地解决了车的放置的问题。


    考虑畸形情况。

    将原棋盘分为三个部分:

    (f_{i,x,y,z}) 表示 (1)(i) 行三个部分各放了 (x,y,z) 个车的方案数。然后像上文一样做就行了。

    本题十分毒瘤,所以要高精度。

    代码:

    struct node   // 高精度
    {
    	int a[50];
        int &operator [](int x){return a[x];}
    	node()
    	{
    		memset (a, 0, sizeof a);
    	}
    	inline void print()
    	{
    		for (int i = a[0]; i >= 1; i--)
    			printf ("%d", a[i]);
    	}
    	
    }f[N * 2][N][N][N], ans;
    
    node operator +(node A, node B)  
    {
    	int s = 0, g = 0;
    	node C;
    	int len = max(A[0], B[0]);
    	for (int i = 1; i <= len + 10; i++)
    	{
    		s = A[i] + B[i] + g, g = s / 10;
    		C[i]= (s % 10);
    		if (!s && !g && i > len) break;
    		C[0] = i; 
    	}
    	return C;
    }
    
    node operator * (node A, ll a)  
    {
    	int s = 0, g = 0;
    	node C;
    	int len = A[0];
    	for (int i = 1; i <= len + 10; i++)
    	{
    		s = A[i] * a + g, g = s / 10;
    		C[i] = s % 10;
    		if (!s && !g && i > len) break;
    		C[0] = i; 
    	}
    	return C;
    }
    
    int n, m, w, h, k, W, H;
    
    bool check(int x, int y)
    {
        if (x <= n && y <= n) return 1;
        if (x > w && x <= w + m && y > h && y <= h + m) return 1;
        return 0;
    }
    
    int main()
    {
    	scanf ("%d%d%d%d%d", &n, &m, &w, &h, &k);
    	if (w >= n) w = n;
    	if (h >= n) h = n;
    	if (m + w <= n && m + h <= n) h = w = 0, m = n;
    	
    	H = max(h + m, n), W = max(m + w, n);
    	int w1 = w, w2 = min(w + m, n), w3 = max(w + m, n);
    	int n1 = w1, n2 = w2 - w1, n3 = w3 - w2;
    	f[0][0][0][0][0] = f[0][0][0][0][1] = 1;
    	for (int i = 0; i < H; ++i)
    	{
    		for (int x = 0; x <= n1; ++x)
    		if (x <= k)
    			for (int y = 0; y <= n2; ++y)
    			if (x + y <= k)
    				for (int z = 0; z <= n3; ++z)
    				if (x + y + z <= k)
    				{
    					f[i + 1][x][y][z] = f[i][x][y][z] + f[i + 1][x][y][z];
    					if(check(w1, i + 1)) f[i + 1][x + 1][y][z] = f[i + 1][x + 1][y][z] + (f[i][x][y][z] * (n1 - x));
    					if(check(w2, i + 1)) f[i + 1][x][y + 1][z] = f[i + 1][x][y + 1][z] + (f[i][x][y][z] * (n2 - y));
    					if(check(w3, i + 1)) f[i + 1][x][y][z + 1] = f[i + 1][x][y][z + 1] + (f[i][x][y][z] * (n3 - z));
    				}
    	}
    	for (int x = 0; x <= n1; ++x)
    		for (int y = 0; y <= n2; ++y)
    			for (int z = 0; z <= n3; ++z)
    			if (x + y + z == k)
    			{
    				ans = ans + f[H][x][y][z];
    			}
    			
    	ans.print();
        return 0;
    }
    
  • 相关阅读:
    redis 学习(一)
    spring 学习总结(一)
    Struts2 学习(三)
    Python3 高级特性
    Python3 模块
    Python3 函数式编程
    Python3 函数
    Python3 列表
    Python3 字符编码
    Java Servlet 回顾
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14115950.html
Copyright © 2020-2023  润新知