牛客月赛28-迷宫

I

题意:
就是给你一个n*m的矩阵,然后从1,1走到n,m,每次可以往下或者往右,并且走过的地方把权值加上,并且%1e4+7,问你又多少种不同的方式走到n,m的时候能获得多少种权值和。

思考:
这就是状态类型的dp了,但是你看这个数据范围卡的有点极限,如果直接定义dp为走到i,j的时候并且总和为k,这种状态是否可达。复杂度会到1e8。其实有时候还是可以过的,这个就可以直接转移就行了。当然还有一种操作就是bitset,bitset就是可以表示状态,和他有的值的个数。一些表示当前点可以到达哪些点的时候可以用他,比如可达性统计这道题,当然这里用bitset还有一些操作。

代码:

int T,n,m,k;
int va[105][105];
bool dp[105][105][mod]; 

signed main()
{
	IOS;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>va[i][j];
			va[i][j] %= mod;
		}
	}
	dp[1][1][va[1][1]] = 1;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			for(int k=0;k<mod;k++)
			{
				dp[i][j][(va[i][j]+k)%mod] |= dp[i-1][j][k];
				dp[i][j][(va[i][j]+k)%mod] |= dp[i][j-1][k];
			}
		}
	}
	int ans = 0;
	for(int i=0;i<mod;i++) ans += dp[n][m][i];
	cout<<ans;
	return 0;
}
bitset版本
int T,n,m,k;
int va[105][105];
bitset<30000> dp[105][105];

signed main()
{
	IOS;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>va[i][j];
			va[i][j] %= mod;
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(i==1&&j==1) dp[i][j][va[i][j]] = 1;
			else if(i==1) dp[i][j] |= (dp[i][j-1]<<va[i][j]);
			else if(j==1) dp[i][j] |= (dp[i-1][j]<<va[i][j]);
			else
			{
				dp[i][j] |= (dp[i-1][j]<<va[i][j]);
				dp[i][j] |= (dp[i][j-1]<<va[i][j]);
			}
			dp[i][j] |= dp[i][j]>>mod;
		}
	}
	int ans = 0;
	for(int i=0;i<mod;i++) ans += dp[n][m][i];
	cout<<ans;
	return 0;
}

总结:
多多积累经验,尝试尝试。

上一篇:C语言每日一练——第105天:杨辉三角形


下一篇:redis成长之路——(一)