TopCoder SRM 576

div.1

T1

题意

有一个n*m的图,一些单元格的底部有可以站立的平面,最下面一行都有
如果两个单元都包含平台并且| i1-i2 |,则Manao可以在两个单元(i1,j)和(i2,j)之间爬行
只有一个单元格包含金币
找到最短的梯子使得可以取到金币

#include 
using namespace std;
int a[100][100],d[100][100],n,m;
queue< pair<int,int> > q;
class ArcadeManao {
public:
    int shortestLadder( vector <string> level, int coinRow, int coinColumn ) ;
};
bool check(int x,int y)
{
	return x>=1&&y>=1&&x<=n&&y<=m&&a[x][y]&&!d[x][y];
}
void sol(int u)
{
	memset(d,0,sizeof(d));
	q.push(make_pair(n,1));
	d[n][1]=1;
	int x,y,i;
	while(!q.empty())
	{
		pair<int,int>w;
		w=q.front();
		q.pop();
		x=w.first;
		y=w.second;
		if(check(x,y-1)) q.push(make_pair(x,y-1)),d[x][y-1]=1;
		if(check(x,y+1)) q.push(make_pair(x,y+1)),d[x][y+1]=1;
		for(i=-u;i<=u;i++)
			if(check(x+i,y))
				q.push(make_pair(x+i,y)),d[x+i][y]=1;
	}
}
int ArcadeManao::shortestLadder(vector <string> s, int sx, int sy) {
	int j,l,r,mid,i;
    n=s.size();
    m=s[0].size();
    l=0;
    r=n;
    memset(a,0,sizeof(a));
    for(i=0;i<n;i++)
    	for(j=0;j<m;j++)
    		if(s[i][j]=='X') a[i+1][j+1]=1;
    while(l<r)
    {
    	mid=(l+r)>>1;
    	sol(mid);
    	if(d[sx][sy]) r=mid;
    	else l=mid+1;
    }
	return l;
}

T2

题意

房间的天花板上有N个落差计数器。 跌落计数器0与房间左端相距0.5厘米,下一个附着在前一个的右边1厘米处。
M个海绵放在房间里,长度都是L厘米,
实验要求海绵的附着方式是每分钟吸收[a,b]滴。
问 有多少种方法可以做到这一点

#include 
using namespace std;
const int mod=1e9+9;
int a[1000],s[1000],d[510][510],g[510][510],h[510][510];
class TheExperiment {
public:
    int countPlacements( vector <string> intensity, int M, int L, int A, int B ) ;
};
int TheExperiment::countPlacements(vector <string> in, int m, int len, int l, int r) {
    int i,j,n=0,k;
    for(i=0;i<in.size();i++)
    	for(j=0;j<in[i].size();j++)
    		a[++n]=in[i][j]-'0';
	s[0]=0;
    for(i=1;i<=n;i++)
    	s[i]=s[i-1]+a[i];
    memset(h,0,sizeof(h));
    h[0][0]=1;
    for(i=1;i<=n;i++)
    {
    	h[i][0]=1;
    	for(j=1;j<=m;j++)
    	{
    		for(k=1;k<len;k++)
    			if(i>=k&&l<=s[i]-s[i-k]&&s[i]-s[i-k]<=r)
    				d[i][j]=((d[i][j]+d[i-k][j-1])%mod+h[i-k][j-1])%mod;
    		for(k=1;k<=len;k++)
    			if(i>=k&&l<=s[i]-s[i-k]&&s[i]-s[i-k]<=r)
    				g[i][j]=(g[i][j]+g[i-k][j-1])%mod;
    		if(i>=len&&l<=s[i]-s[i-len]&&s[i]-s[i-len]<=r)
    			g[i][j]=((g[i][j]+d[i-len][j-1])%mod+h[i-len][j-1])%mod;
    		h[i][j]=(g[i-1][j]+h[i-1][j])%mod;
    	}
    }
    return (g[n][m]+h[n][m])%mod;
}

div2

T3

题意

Manao有一个矩阵X,有10,000行和W列。
他选择一个由最多W个小写字母组成的字符串S
cur := 0
for i := 0 to 9999
for j := 0 to W - 1
X[i][j] := S.charAt(cur)
cur := (cur + 1) mod length(S)
用这个来填充这个矩阵
计算Manao可以使用多少个不同的生成器来创建包含您给出的片段的矩阵X

#include 
using namespace std;
const int mod=1e9+9;
long long d[1010][1010];
class CharacterBoard2 {
public:
    int countGenerators( vector <string> fragment, int W, int i0, int j0 ) ;
};
int sol(int a,int y)
{
	long long w=1,x=a;
	while(y>0)
	{
		if(y&1) w=(w*x)%mod;
		x=(x*x)%mod;
		y=y>>1;
	}
	return (int)w;
}
int CharacterBoard2::countGenerators(vector <string> a, int w, int i0, int j0) {
	long long ans=0;
	int n,m,i,j,k,x,cnt,temp;
	string s;
	n=a.size();
	m=a[0].size();
	for(i=0;i<n;i++)
		for(j=0;j<m;j++)
			d[i][j]=((i+i0)*w+(j+j0))%mod;
	for(k=1;k<=w;k++)
	{
		s.assign(k,'#');
		x=1;
		cnt=0;
		for(i=0;i<n;i++)
		{
			for(j=0;j<m;j++)
			{
				temp=d[i][j]%k;
				if(s[temp]=='#')
				{
					s[temp]=a[i][j];
					cnt++;
				}
				else if(s[temp]!=a[i][j])
				{
					x=0;
					break;
				}
			}
			if(x==0) break;
		}
		if(x==0) continue;
		ans=(ans+sol(26,k-cnt))%mod;
	}
	return static_cast<int> (ans);
}

你可能感兴趣的:(TopCoder,题解)