topcoder srm 706 div1 -1000

1、给定一个迷宫,点号表示不可行,井号表示可行。现在可以改变其中的一些井号的位置。问最少改变多少个井号可以使得从左上角到右下角存在路径。

思路:设高为$n$,宽为$m$,若井号的个数$S$小于$n+m-1$则无解。否则最多改变$n+m-1$个井号即可。令$f[x][y][k]$表示现在到达位置$(x,y)$且中途经过的点号格子数为$k$时最少经过了多少井号格子。这样进行搜索即可。搜过过程中,应该满足$k\leq n+m-1$且$k+f[x][y][k]\leq S$。

#include <iostream>
#include <set>
#include <stdio.h>
#include <queue>
#include <algorithm>
#include <string.h>
using namespace std;

const int N=20;

int f[N][N][N+N];
int inq[N][N][N+N];
int h[N][N][N+N];

const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};

struct node
{
    int x,y,p;

    node(){}
    node(int _x,int _y,int _p):
        x(_x),y(_y),p(_p) {}
};

queue<node> Q;

void add(int x,int y,int p,int c)
{
    if(!h[x][y][p]||f[x][y][p]>c)
    {
        h[x][y][p]=1;
        f[x][y][p]=c;
        if(!inq[x][y][p])
        {
            inq[x][y][p]=1;
            Q.push(node(x,y,p));
        }
    }
}

class MovingCandies
{
public:
    int minMoved(const vector<string> t)
    {

        const int n=(int)t.size();
        const int m=(int)t[0].size();

        int S=0;
        for(int i=0;i<n;++i) for(int j=0;j<m;++j) S+=t[i][j]==‘#‘;
        if(S<n+m-1) return -1;

        if(t[0][0]==‘.‘) add(0,0,1,0);
        else add(0,0,0,1);
        while(!Q.empty())
        {
            const int x=Q.front().x;
            const int y=Q.front().y;
            const int p=Q.front().p;
            const int c=f[x][y][p];
            Q.pop();
            inq[x][y][p]=0;
            if(x==n-1&&y==m-1) continue;

            for(int d=0;d<4;++d)
            {
                const int xx=x+dx[d];
                const int yy=y+dy[d];
                if(xx>=0&&xx<n&&yy>=0&&yy<m)
                {
                    const int pp=p+(t[xx][yy]==‘.‘);
                    const int cc=c+(t[xx][yy]==‘#‘);
                    if(pp>n+m-1||pp+cc>S) continue;
                    add(xx,yy,pp,cc);
                }
            }

        }

        for(int i=0;i<=n+m-1;++i)
        {
            if(h[n-1][m-1][i]) return i;
        }
        return -1;
    }
};

  

2、给定一个整数数组,每个数字可以被替换成字符ABC中的一个,相同的数组必须被相同的字符替换。问在被任意替换得到的所有不同的字符串中,包含子列ABC的串有多少个。

思路:一个简单的思路是分别枚举第一个A、第一个B、第一个C出现的位置,这样整个串被分成4部分,第一部分中不能出现A,第二部分不能出现B,第三部分不能出现C。这样复杂度是$O(N^{3})$。现在只枚举第一个A第一个B,然后后面字符任意的总数为$X$,不包含C的总数为$Y$,那么此次枚举对答案的贡献为$X-Y$。这样是$O(N^{2})$的复杂度。实现如代码所示。其中$f[i][j]=0$表示数字$i$可以被替换成字符$j$,$j=0$表示A,$j=1$表示B,$j=2$表示C。$tot[j]$表示有多少种数字有$j$种替换方式。

#include <string.h>
#include <stdio.h>
#include <vector>
using namespace std;

const int mod=1000000007;
const int N=3005;

int p[4][N];
int tot[4];
int f[N][4];
int appears[N];

class MappingABC
{

	void init()
	{
		for(int i=0;i<4;++i)
		{
			p[i][0]=1;
			for(int j=1;j<N;++j) p[i][j]=((long long)p[i][j-1]*i%mod);
		}
	}

	void clear()
	{
	    memset(f,0,sizeof(f));
	    memset(tot,0,sizeof(tot));
	}

	int get()
	{
		int ans=1;
		for(int i=0;i<4;++i) ans=((long long)ans*p[i][tot[i]]%mod);
		return ans;
	}

	int cal(int x)
	{
		int c=0;
		for(int i=0;i<3;++i) if(f[x][i]==0) ++c;
		return c;
	}

	void add(int x,int y)
	{
		--tot[cal(x)];
		++f[x][y];
		++tot[cal(x)];
	}
	void sub(int x,int y)
	{
		--tot[cal(x)];
		--f[x][y];
		++tot[cal(x)];
	}

public:
    int countStrings(vector<int> t)
	{
		const int n=(int)t.size();
		for(int i=0;i<n;++i) appears[t[i]]=1;
		init();
		int ans=0;
		const int A=0,B=1,C=2;
		for(int k=0;k<2;++k)
		{
			const int NO_C=k==1;
			for(int a=0;a<n;++a)
			{
				clear();
				for(int i=0;i<N;++i) if(appears[i]) ++tot[3];
				for(int i=0;i<a;++i) add(t[i],A);
				add(t[a],B);
				add(t[a],C);
				if(NO_C)
				{
					for(int i=a+1;i<n;++i) add(t[i],C);
				}
				for(int b=a+1;b<n;++b)
				{
					if(NO_C) sub(t[b],C);
					add(t[b],A);
					add(t[b],C);
					if(NO_C) ans=(ans-get())%mod;
					else ans=(ans+get())%mod;
					sub(t[b],A);
					sub(t[b],C);
					add(t[b],B);
				}
			}
		}
		if(ans<0) ans+=mod;
		return ans;
	}

};

  

时间: 2024-10-05 16:01:56

topcoder srm 706 div1 -1000的相关文章

topcoder srm 704 div1 -1000

1.对于一棵树上的一个节点$u$,定义$f(u)$表示树上距离$u$最远的节点到$u$的距离.给出每个节点的$f$值,构造出这棵树. 思路:找到树的主干,然后不在主干上的节点一定可以连接到主干的某个节点上. #include <iostream> #include <map> #include <string> #include <stdio.h> #include <vector> #include <set> #include &

Topcoder SRM 648 Div2 1000

Problem 给一个长度为N的字符串S,S只含有'A'.'B'.'C'三种元素.给定一个K,要求返回字符串S,使得S中恰好有K对pair(i,j)满足 0=<i<j<N,且 S[i]<S[j].若不存在,则返回空串. Limits Time Limit(ms): 2000 Memory Limit(MB): 256 N: [3, 30] K: [0, N*(N-1)/2 ] Solution 设S中含有n1个'A',n2个'B',n3个'C',设num=n1*n2+n1*n3+n

Topcoder SRM 643 Div1 250&lt;peter_pan&gt;

Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*......*pn,我们假设p0,p1,...,pn是单调不降的,那么v里存储的是下标为偶数 的N的质因数p0,p2,p4,...,p(2k).现在要求写一个程序,返回一个vector<long long>ans; ans里存储的是p0,p1,p2,...,pn. Limits Time Limit(m

TOPCODER SRM 686 div2 1000

// TOPCODER SRM 686 div2 1000 Problem Statement 给出一个至多长 100 的字符串,仅包含 ( 和 ),问其中有多少个不重复的,合法的括号子序列. 子序列可以不连续:合法即括号序列的合法:答案模 1,000,000,007. Examples "(())(" Returns: 2 Correct non-empty bracket subsequences are "()" and "(())". &

Topcoder SRM 648 Div1 250

Problem 给一个长度为N的"AB"字符串S,S只含有两种字符'A' 或 'B',设pair(i,j)(0=<i<j<N)表示一对 i,j 使得S[i]='A',S[j]='B'.现给定一个K,求字符串S,使得pair(i,j)的个数恰好为K.若不存在,则返回空串. Limits Time Limit(ms): 2000 Memory Limit(MB): 256 N: [2, 50] K: [0 , N*(N-1)/2 ] Solution 若K>(N/2

Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串

Problem Statement      The Happy Letter game is played as follows: At the beginning, several players enter the field. Each player has a lowercase English letter on their back. The game is played in turns. In each turn, you select two players with dif

Topcoder Srm 673 Div2 1000 BearPermutations2

\(>Topcoder \space Srm \space 673 \space Div2 \space 1000 \space BearPermutations2<\) 题目大意 : 对于一个长度为 \(n\) 的排列,定义其的贡献为对其建笛卡尔树,树上有两个儿子的节点其左右儿子在原排列中的距离之和,给出 \(n, Mod\),求所有长度为 \(n\) 的排列的贡献之和对 \(Mod\) 取模的值 \(1 \leq n \leq 100\) 解题思路 : 考虑一个最暴力的 \(dp\) ,设

topcoder srm 738 div1 FindThePerfectTriangle(枚举)

Problem Statement      You are given the ints perimeter and area. Your task is to find a triangle with the following properties: The coordinates of each vertex are integers between 0 and 3000, inclusive. The perimeter of the triangle must be exactly

Topcoder SRM 547 Div1 250

Problem On a horizontal line, there are two vertical pillars. The distance between their bottoms is w. The height of the first pillar is an integer, chosen uniformly at random in the range 1 through x, inclusive. The height of the second pillar is an