题解 CF293B 【Distinct Paths】

博客介绍了如何解决竞赛编程题目CF293B「Distinct Paths」。作者指出初始的n, m限制是误导性的,实际问题规模远小于1000。当n + m - 1 > k时,问题无解。为了解决这个问题,提出了采用深度优先搜索(DFS)的方法,并进行了剪枝优化:包括可行性剪枝(若剩余步数大于可用颜色则剪枝)和对称性剪枝(首次填充颜色的对称变换不影响结果)。优化后的DFS策略显著减少了搜索量,使得即使在棋盘稀疏的情况下也能快速求解。" 88186145,8092602,CSS样式处理:文字溢出与背景图片技巧,"['前端开发', 'CSS', 'HTML', '布局', '背景图片']

这个n,m≤1000n,m≤1000nm1000明显是唬人的,我们经过研究后可以发现,当n+m−1>kn + m - 1>kn+m1>k时就无解了。因此我们发现,n,m的实际范围是非常小的,因此考虑dfs。
但是单纯的dfs时间复杂度仍不足以通过此题,我们考虑优化:

1.可行性剪枝。若剩下步数大于可用颜色就剪掉

  1. 对称性剪枝。如果当前是第一次填颜色x,那么把x换成其他第一次填的颜色结果不变

这样就使的搜索量大大减少,即使棋盘相当稀疏也能瞬间出解

Code

#include <cstdio>
#include <cstring>
#define lowbit(x) ((x) & (-(x)))
#define Int register int
using namespace std;

const int MOD = 1000000007;

int rc[1007][1007] , n , m , k , ans;
int rec[1007][1007] , used[1000007];

inline int dfs(Int x , Int y) 
{
    if (y > m) y = 1 , ++ x;
    if (x == n + 1) return 1;
    int now = rec[x - 1][y]|rec[x][y-1],tmp=-1;
    int ret = 0 , tot = 0;
    for (Int i = 1 ; i <= k ; ++ i) tot += !((1 << i - 1) & now);
    if (n + m - x - y + 1 > tot) return 0;
    for (Int i = 1 ; i <= k ; ++ i) 
	{
        if ((1 << i - 1) & now) continue;
        if (!rc[x][y] || rc[x][y] == i) 
		{
            rec[x][y] = now | (1 << i - 1);
            if (++ used[i] == 1) 
			{
                if (tmp == -1) tmp = dfs(x , y + 1);
                ret += tmp;
            } else ret += dfs(x , y + 1);
            ret %= MOD;
            -- used[i];
        }
    }
    return ret;
}

int main(void) 
{
    int cnt = 0; 
	scanf("%d%d%d" , &n , &m , &k);
    if (n + m - 1 > k) {putchar('0'); return 0;}
    for (Int i = 1 ; i <= n ; ++ i)
		for (Int j = 1 ; j <= m ; ++ j)
		{
        	scanf("%d",&rc[i][j]);
        	cnt += (!rc[i][j]); 
			++ used[rc[i][j]];
    	}
    printf("%d\n" , dfs(1 , 1));
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值