2019.1.26 Contest1075 - 动规专题测试

Contest1075 动规专题测试

T1:MZOJ1348: 公交换乘

在这里插入图片描述

思路

很显然,设计f i表示在i节点时的最小值
如何转移?f i可以由f i-1,f i-2,f i-3……转移过来,所以在这里插入图片描述
son从1~n

code如下:

/*	NAME:EPSILON
	WAY: DP
	LANG:C++
	TIME:7:56
*/
#include <bits/stdc++.h>
using namespace std;
int final;
int f[250],cost[250];
int read()
{
	char ch=getchar();int x=0;
	while(ch<'0' || ch>'9')ch=getchar();
	while(ch>='0' && ch<='9')
	{
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x;
}

void readdata()
{
	for(int i=1;i<=10;i++)cost[i]=read();
	final=read();
}

void init()
{
	freopen("A.in","r",stdin);
}

void work()
{
	memset(f,0x7f7f,sizeof(f));
	f[0]=0;f[1]=cost[1];
	for(int i=1;i<=10;i++)
	for(int j=0;j+i<=200;j++)
	{
		if (f[j+i]>f[j]+cost[i]) f[j+i]=f[j]+cost[i];
	}
	printf("%d",f[final]);
}

int main()
{
	init();
	readdata();
	work();
	return 0;
}

T2:1349: 数字矩形

在这里插入图片描述

思路

每一个各自是由上,右,左推而来的,令f ij表示i行j列的最小值
注意几个小细节(就是一个ans=INT_MAX害得失了50分
递推顺序及方程:
在这里插入图片描述
code:

	/*	NAME:EPSILON
	WAY: DP
	LANG:C++
	TIME:8:40
*/


#include <bits/stdc++.h>
using namespace std;
const int maxn=505;
int n,m;
int mapp[maxn][maxn];
int f[maxn][maxn];
int read()
{
	char ch=getchar();int x=0;
	while(ch<'0' || ch>'9')ch=getchar();
	while(ch>='0' && ch<='9')
	{
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x;
}

void readdata()
{
	n=read(),m=read();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			mapp[i][j]=read();
}

void init()
{
	freopen("B.in","r",stdin);
}

void work()
{
	for(int i=1;i<=m;i++)f[0][i]=0;
    for(int i=1;i<=n;i++)//每一行 
    {
        for(int j=1;j<=m;j++) f[i][j]=f[i-1][j]+mapp[i][j];//边界,下 
        for(int j=2;j<=m;j++)f[i][j]=min(f[i][j],f[i][j-1]+mapp[i][j]);//左 
        for(int j=m-1;j>=1;j--)f[i][j]=min(f[i][j],f[i][j+1]+mapp[i][j]);

	int ans=INT_MAX;
	for(int i=1;i<=m;i++)	ans=min(ans,f[n][i]);
	printf("%d",ans);
}

int main()
{
	init();
	readdata();
	work();
	return 0;
}

重头戏:MZOJ 1350: 排列 (SCOI2007)

状压DP

思路

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
至此,算法框架已经大致出来:
code

#include <bits/stdc++.h>
using namespace std;
int T,mod,l,ans,sum,r,x;
char s[15];
int f[15];
int dp[5005][1005];
void init()
{
	freopen("MZOJ1350.in","r",stdin);
}

void work()
{
	ans=dp[(1<<l)-1][0];
	for(int i=0;i<10;i++)
	{
		sum=0;
		for(int j=0;j<l;j++)
		{
			if(i==f[j])sum++;
		}
		r=1;
		for(int j=1;j<=sum;j++)
		{
			r=r*j;
		}
		ans=ans/r;
	}
	printf("%d\n",ans);
}

void readdata()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%s%d",s,&mod);
		l=strlen(s);
		for(int i=0;i<l;i++)
		{
			f[i]=s[i]-'0';
		}
		for(int i=0;i<(1<<l);i++)
			for(int k=0;k<mod;k++)
				dp[i][k]=0;
		dp[0][0]=1;
////////////////////////////边界处理/////////////////////////////
////////////////////////////状压动归///////////////////////////// 
		for(int i=0;i<(1<<l);i++)
		{
			for(int k=0;k<mod;k++)
			{
				if(dp[i][k])//如果可行
				{
					for(int j=0;j<l;j++)
					{
						if((i&(1<<j))==0)
						{
							dp[i|(1<<j)][(k*10+f[j])%mod]+=dp[i][k];
						}
					}
				} 
			}
		}
		work(); 		
	}
}



int main()

{
	init();
	readdata();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_25845753/article/details/86661381