Regionals 2013 Asia - Daejeon (部分题目题解)

题目链接:Regionals 2013 Asia - Daejeon 

6500 Boxes

题意:将箱子(矩阵的1)全移动到矩阵的底部需要几步

思路:按列从下到上统计。(n,m)的矩阵,移动一个箱子(x,y),如果有c个箱子在底部,那么移动该箱子的步数是(n-x-c-1)。

AC代码:

#include 
#include 
int mp[110][110];

int main()
{
	int t;
	int i,j,n,m;

	scanf("%d",&t);
	while(t--){
		scanf("%d %d",&n,&m);
		for(i=0;i=0;i--){
				if(mp[i][j]){
					ans+=(n-i-c-1);
					c++;
				}
			}
		}
		printf("%d\n",ans);
	}
return 0;
}

/*
3
5 4
1 0 0 0
0 0 1 0
1 0 0 1
0 1 0 0
1 0 1 0

3 3
1 1 1
0 0 0
0 0 0
*/


6506 Padovan Sequence

题意:用等边三角组成多边形,每次所增加的正三角形的边长都是该多边形最长的边。(表述的不好,看题中的图会明白很多)

思路:找规律,发现f[i]=f[i-2]+f[i-3]。注意long long 

#include 
#define LL long long 
LL ans[110];
void init(){
	ans[1]=1,ans[2]=1,ans[3]=1,ans[4]=2,ans[5]=2;
	LL i;
	for(i=6;i<=100;i++){
		ans[i]=ans[i-2]+ans[i-3];
	}
}

int main()
{
	LL t;
	LL n;
	init();
	scanf("%lld",&t);
	while(t--){
		scanf("%lld",&n);
		printf("%lld\n",ans[n]);
	}

return 0;
}


6508 Permutation Graphs

题意:给出两个序列把他们数字相同连线,求交点的个数

思路:将第一串数字编号,第二串按照编号译码,答案就是第二串译码后的逆序数

1 5 3 4 2 7 6

7 1 5 3 4 2 6

编号:

(1 5 3 4 2 7 6)一一对应(1 2 3 4 5 6 7)

(7 1 5 3 4 2 6)得到(6 1 2 3 4 5 7)

(6 1 2 3 4 5 7) 的逆序数为5

画个图看下比较清晰些。


AC代码:

#include 
#include 
#include 
#include 
using namespace std;
int a[100010];
int n,c[100003];
int x[100010];
vector s;
vector::iterator it;
int lowbit(int x) {
	return x&(-x);
}
int sum(int x)
{
	int sum=0;
	while(x<=n) {
		sum+=c[x];
		x+=lowbit(x);
	}
	return sum;
}
void inster(int x,int i) {
	while(x>0) {
		c[x]+=i;
		x-=lowbit(x);
	}
}

int main()
{
	int t;
	int i;

	scanf("%d",&t);
	while(t--){
		s.clear();
		memset(c,0,sizeof c);
		scanf("%d",&n);
		for(i=0;i




6510 Stickers

题意:给出一个2*n的矩阵,取数使得到的结果最大,要求取的数不能有公共边。

思路:dp[i][j]表示前i列,状态j所取数的最大值,j==0 表示不取,j==1表示去第1行的数,j==2表示取第2行的数。状态转移见代码

AC代码:

#include 
#include 
#include 

using namespace std;

int dp[100010][5];//0 都不选 1选上面一张(0)。2选下面一张(1)
int mp[5][100010];

int main()
{
	int t;
	int i,j,n;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(i=1;i<=2;i++){
			for(j=0;j




6511 Term Project

题意: 给出n对关系,问这个n对关系中不在 成环(自环也算)中的个数。

思路:有向图的强连通,先处理自环,在计算如果强连通分量中点的个数大于1,说明成环,答案就是(n-环中的点数)

AC代码:

#include 
#include 
#include 
using namespace std;
const int MAXN = 100010;//点数
const int MAXM = 100010;//边数
struct Edge
{
	int to,next;
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc
int Index,top;
int scc;//强连通分量的个数
bool Instack[MAXN];
int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc
//num数组不一定需要,结合实际情况
void addedge(int u,int v)
{
	edge[tot].to = v;
	edge[tot].next = head[u];
	head[u] = tot++;
}
void Tarjan(int u)
{
	int v;
	Low[u] = DFN[u] = ++Index;
	Stack[top++] = u;
	Instack[u] = true;
	for(int i = head[u];i != -1;i = edge[i].next)
	{
		v = edge[i].to;
		if( !DFN[v] )
		{
			Tarjan(v);
			if( Low[u] > Low[v] )Low[u] = Low[v];
		}
		else if(Instack[v] && Low[u] > DFN[v])
			Low[u] = DFN[v];
	}
	if(Low[u] == DFN[u])
	{
		scc++;
		do
		{
			v = Stack[--top];
			Instack[v] = false;
			Belong[v] = scc;
			num[scc]++;
		}
		while( v != u);
	}
}
void solve(int N)
{
	memset(DFN,0,sizeof(DFN));
	memset(Instack,false,sizeof(Instack));
	memset(num,0,sizeof(num));
	Index = scc = top = 0;
	for(int i = 1;i <= N;i++)
		if(!DFN[i])
			Tarjan(i);
}
void init()
{
	tot = 0;
	memset(head,-1,sizeof(head));
}

int main()
{
	int t;
	int i,n,a;
	scanf("%d",&t);
	while(t--){
		init();
		int ans=0;
		scanf("%d",&n);
		for(i=1;i<=n;i++){
			scanf("%d",&a);
			addedge(i,a);
			if(i==a) ans++;
		}
		solve(n);
		//printf("%d\n",scc);
		for(i=1;i<=scc;i++){
			if(num[i]>1) ans+=num[i];
		}
		printf("%d\n",n-ans);
	}
	return 0;
}
/*
2
7
3 1 3 7 3 4 6
8
1 2 3 4 5 6 7 8

3
3
2 3 1
3
1 2 3

6
2 3 1 5 4 6
*/


你可能感兴趣的:(套题,dp,UVALive,dp,强连通,逆序数)