codeforces红名训练

1.CF2B(字典序输出 10的判断)

1.dfs与bfs有2的1000次方种选择 时间一定会爆

2.dp的模板 (1)单调 (2)无后效性 (3)在前面两个中选择

3.如果对于搜索进行最优剪枝,也可也变成dp 但是为何不直接用dp?dp之所以快于搜索,因为搜索会进行根本到不了结果的道路。

4.为什么是min(2,5)因为答案的后导零一定是由2*5组成。那么min(2,5)一定对映着答案零的个数

#include<cstdio>
#include<algorithm>
using namespace std;
const int Inf=0x7FFFFFFF;//七个F代表最大
int n,t,num[1002][1002][2],f[1002][1002][2];
void Print(int i,int j,int k) {//k=0代表R k=1代表D
    if(i==1&&j==1) {                //递归输出函数
        putchar(k? 'D':'R');
        return ;            //边界
    }
    if(i==1)
        Print(i,j-1,0);
    else if(j==1)
        Print(i-1,j,1);
    else if(f[i][j][t]==f[i][j-1][t]+num[i][j][t])
        Print(i,j-1,0);
    else
        Print(i-1,j,1);
    if(i!=n||j!=n)
        putchar(k? 'D':'R');    //在(n,n)处不输出
}
int main() {
    int ans;
    scanf("%d",&n);
    for(int i=1,k;i<=n;++i)
        for(int j=1;j<=n;++j) {        //预处理因子个数
            scanf("%d",&k);
            if(!k) {
                num[i][j][0]=num[i][j][1]=1;
                t=i;    //特判0,记录位置
            }
            else {
                for(;!(k%2);k/=2)
                    ++num[i][j][0];
                for(;!(k%5);k/=5)
                    ++num[i][j][1];
            }
        }
    for(int i=1;i<=n;++i)
        f[0][i][0]=f[i][0][0]=f[0][i][1]=f[i][0][1]=Inf;    //由于转移方程使用min,将边界赋为最大值
    f[1][1][0]=num[1][1][0];
    f[1][1][1]=num[1][1][1];
    for(int k=0;k<2;++k)
        for(int i=1;i<=n;++i)
            for(int j=i==1? 2:1;j<=n;++j)
                f[i][j][k]=min(f[i][j-1][k],f[i-1][j][k])+num[i][j][k];
    ans=min(f[n][n][0],f[n][n][1]);
    if(t&&ans>1) {            //情况2 按照字典序输出 先下后右再下一定经过0
        printf("1\n");
        for(int i=1;i<t;++i)
            putchar('D');
        for(int i=1;i<n;++i)
            putchar('R');
        for(int i=t;i<n;++i)
            putchar('D');
    }
    else {                    //情况1
        printf("%d\n",ans);
        t=!(f[n][n][0]<f[n][n][1]);
        Print(n,n,0);//递归输出字典序
    }
    return 0;
}

2. p1027 (floyd 矩形 距离)

1.两点之间最短距离(带权值)

2.数组处理城市 用一维数组解决

3.Floyd n的三次方时间

4.待处理 结构体存储节点 使用spfa dijkstra

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>

using namespace std;
int n,s,tt,a,b;
double x[101][5],dis[601][601],y[101][5],t[101];
double gd(double xa,double ya,double xb,double yb)//距离公式 
{
	return sqrt((xa-xb)*(xa-xb)+(ya-yb)*(ya-yb));
}
int id(int i,int j)//城市中飞机站的id 
{
	return (i-1)*4+j;
}
int main()
{
	scanf("%d",&n);
	for(int T=1;T<=n;T++)
	{
		double ans=2147483647;
		for(int i=1;i<=101;i++)
		{
			for(int j=1;j<=101;j++)
			{
				dis[i][j]=2147483647;
			}
		}
		scanf("%d%d%d%d",&s,&tt,&a,&b);
		for(int i=1;i<=s;i++)
		{
			for(int j=1;j<=3;j++)
			{
				scanf("%lf",&x[i][j]);
				scanf("%lf",&y[i][j]);
			}	
			double da=gd(x[i][1],y[i][1],x[i][2],y[i][2]);
			double db=gd(x[i][1],y[i][1],x[i][3],y[i][3]);
			double dc=gd(x[i][2],y[i][2],x[i][3],y[i][3]);
			double maxn=0;
			if(da>db&&da>dc)
				x[i][4]=x[i][1]+x[i][2]-x[i][3],
				y[i][4]=y[i][1]+y[i][2]-y[i][3];
			if(db>da&&db>dc)
				x[i][4]=x[i][1]+x[i][3]-x[i][2],
				y[i][4]=y[i][1]+y[i][3]-y[i][2];
			if(dc>da&&dc>db)
				x[i][4]=x[i][2]+x[i][3]-x[i][1],
				y[i][4]=y[i][2]+y[i][3]-y[i][1];
			scanf("%lf",&t[i]);
		}//算出每个城市的坐标 
	/*	for(int i=1;i<=s;i++)
		{
			for(int j=1;j<=4;j++)
			{
				printf("%d,%d:(%.0lf,%.0lf)",i,j,x[i][j],y[i][j]);
			}
			printf("\n");
		}*/
		for(int i=1;i<=s;i++)
		{
			for(int j=1;j<=4;j++)
			{
				for(int k=1;k<=4;k++)
				{
					if(j==k)continue;
					double d=gd(x[i][j],y[i][j],x[i][k],y[i][k]);
					dis[id(i,j)][id(i,k)]=d*t[i];
				}
			}
		}//每个城市中机场的距离费用 
		for(int i=1;i<=s;i++)
		{
			for(int j=1;j<=4;j++)
			{
				for(int k=1;k<=s;k++)
				{
					if(i==k)continue;
					for(int l=1;l<=4;l++)
					{
						double d=gd(x[i][j],y[i][j],x[k][l],y[k][l]);
						dis[id(i,j)][id(k,l)]=d*tt;
					}
				}
			}
		}//不同城市被中机场之间的费用 
		for(int i=1;i<=s*4;i++)dis[i][i]=0;
		for(int k=1;k<=s*4;k++)
		{
			for(int i=1;i<=s*4;i++)
			{
				for(int j=1;j<=s*4;j++)
				{
					dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
				}
			}
		}
	/*	for(int i=1;i<=4*s;i++)
		{
			for(int j=1;j<=4*s;j++)
			{
				printf("%d~%d:%.1lf\n",i,j,dis[i][j]);
			}
		}*/
		for(int i=4*(a-1)+1;i<=4*a;i++)
		{
			for(int j=4*(b-1)+1;j<=4*b;j++)
			{
				ans=min(ans,dis[i][j]);
			}
		}//城市a 到 b 的最短路 
		printf("%.1lf\n",ans);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值