pat1018

5 篇文章 0 订阅
5 篇文章 0 订阅

个人认为这题在pat里面算是比较难了,主要是有2点,1,可能很多同学理解不了为什么车送出去了还得送回去,现在把问题简化,就给你一串数,a[1],a[2],a[3],,,,a[n],假设为了让这些数都变成一个k,我需要从a[0]拿出一些数,从左往右送,那么我最少需要拿出多少,才能保证后面的n个数都能变成k。2本题自己想了2种方法,第一是自己想出来的,记录所有最短路的路径,然后倒着搜回去,搜到起点做一次比较,找出最优的,另外有一个方法是dij找出最短路后,利用一个比较强的剪枝直接顺着搜。总得来说,这2个搜索都不是很好写,而且本题条件要求很复杂,首先是最短路,多条最短路的情况下,选择拿出最少,拿出最少的情况下选择拿回去最少。

下面说明一下第一个问题,假设这么一串数:

 3  6 2 9 8       k=5

那么到a[1],是少了2辆,记为-2,到a[2],多了一辆(6-5=1),那么总体来说少了1辆,记为-1,依次类推,分别有,-2,-1,-4,0,3 你会发现这串数最难满足的是-4,那么你要在起点拿出4,至于终点还能拿回多少,其实就是到最后你发现就算你不拿,还能多出3辆,但是你不能不拿,你要是不拿,就算你后面多出再多,前面也无法满足,因为他是从前往后送的。你拿了4辆,就多出7辆。所以最终拿回几辆,是最后这个数加上你拿出来的数。

附代码如下:

倒搜记录路径版:

#include<stdio.h>
#include<string.h>
#define inf 0x7FFFFF
int a[501];
int dis[501];
int map[501][501];
int Min(int x,int y)
{
	return x<y?x:y;
}
int mark[501];
int pre[501][501];
int cm,n,sp,m;
int ans[501];
int tmp[501];
int vi[501];

int in,out;

int len;
void dfs(int x,int dep)
{
	int i;
	if(x==0)
	{
		int cc=0;
		int cur1,cur2;
		cur1=inf;
		for(i=dep-1;i>=0;i--)
		{
			cc+=a[tmp[i]]-cm/2;
			if(cc<cur1)
			cur1=cc;
		}
		if(cur1>0)
			cur1=0;
		cur2=-cur1+cc;
		if(cur1>in||( (cur1==in)&&(cur2<out) ) ) 
		{
			in=cur1;
			out=cur2;
			len=dep;
			for(i=dep-1;i>=1;i--)
			ans[i]=tmp[dep-i];
		}
		
	}
	for(i=1;i<=pre[x][0];i++)
	{
		int node=pre[x][i];
		if(vi[node]==0)
		{
			vi[node]=1;
			tmp[dep+1]=node;
			dfs(node,dep+1);
			vi[node]=0;
		}
	}
	return ;
}

int main()
{
	int i,j;
	while(scanf("%d%d%d%d",&cm,&n,&sp,&m)!=EOF)
	{
		for(i=1;i<=n;i++)
		scanf("%d",a+i);
		a[0]=0;
		for(i=0;i<=n;i++)
			for(j=0;j<=n;j++)
			map[i][j]=map[j][i]=inf;
			
		for(i=1;i<=m;i++)
		{
			int a,b,x;
			scanf("%d%d%d",&a,&b,&x);
			map[a][b]=map[b][a]=x;
		}
		
		for(i=1;i<=n;i++)
		{
			dis[i]=map[i][0];
			mark[i]=0;
			if(dis[i]!=inf)
			{
				pre[i][0]=1;
				pre[i][1]=0;
			}
		}
		while(1)
		{
			int min=inf;
			int dd=-1;
			for(i=1;i<=n;i++)
			if(dis[i]<min&&mark[i]==0)
			{
				min=dis[i];
				dd=i;
			}
			mark[dd]=1;
			for(i=1;i<=n;i++)
			{
				if(mark[i]==0)
				{
					if(dis[dd]+map[i][dd]<dis[i])
					{
						dis[i]=dis[dd]+map[i][dd];
						pre[i][0]=1;
						pre[i][1]=dd;
					}
					else if(dis[dd]+map[i][dd]==dis[i])
					{
						pre[i][0]++;
						pre[i][pre[i][0]]=dd;
					}
				}
			}
			if(dd==sp)
				break;
		}
		memset(vi,0,sizeof(vi));
		
		tmp[0]=sp;
		in=-inf;
		out=inf;
		dfs(sp,0);
		int aans=0;
		
		printf("%d ",-in);
		printf("0->");	
		for(i=1;i<len;i++)
			printf("%d->",ans[i]);
		printf("%d %d\n",sp,out);
	}
}
		


 


顺搜剪枝版:

#include<stdio.h>
#include<stdio.h>
#include<string.h>
#define inf 0x7FFFFF
int a[501];
int dis[501];
int map[501][501];
int res1,res2;
int mark[501];

int cm,n,sp,m;
int ans[501];
int tmp[501];
int vi[501];
int nowdep;

void dfs(int x,int d,int dep)
{
	
	if(dis[x]<d)
		return ;
	int i ;
	if(x==sp&&d==dis[sp])
	{
		int cc=0;
		int cur1=inf;
		int cur2;
		for(i=1;i<=dep;i++)
		{
			cc+=a[tmp[i]]-cm/2;
			if(cc<cur1)
				cur1=cc;
		}
		if(cur1>0)
			cur1=0;
		cur2=-cur1+cc;
		
		if(cur1>res1||(  (cur1==res1)&&(res2>cur2) ) )
		{
			res1=cur1;
			res2=cur2;
			for(i=1;i<=dep;i++)
				ans[i]=tmp[i];		
			nowdep=dep;
		}
		return ;
	}
	
	for(i=1;i<=n;i++)
		if(vi[i]==0&&map[i][x]!=inf)
		{
			vi[i]=1;
			tmp[dep+1]=i;
			dfs(i,d+map[i][x],dep+1);
			vi[i]=0;
		}
	return ;
}
		
int main()
{
	int i,j;
	while(scanf("%d%d%d%d",&cm,&n,&sp,&m)!=EOF)
	{
		for(i=1;i<=n;i++)
		scanf("%d",a+i);
		
		for(i=0;i<=n;i++)
			for(j=0;j<=n;j++)
			map[i][j]=map[j][i]=inf;
			
		for(i=1;i<=m;i++)
		{
			int a,b,x;
			scanf("%d%d%d",&a,&b,&x);
			map[a][b]=map[b][a]=x;
		}
		
		for(i=1;i<=n;i++)
		{
			dis[i]=map[i][0];
			mark[i]=0;
		}
		mark[0]=1;
		while(1)
		{
			int min=inf;
			int dd=-1;
			for(i=1;i<=n;i++)
			if(dis[i]<min&&mark[i]==0)
			{
				min=dis[i];
				dd=i;
			}
			mark[dd]=1;
			for(i=1;i<=n;i++)
			{
				if(mark[i]==0&&dis[dd]+map[i][dd]<dis[i])
					dis[i]=dis[dd]+map[i][dd];
			}
			if(dd==sp)
				break;
		}
		res1=-inf;
		res2=inf;
		dfs(0,0,0);
		printf("%d ",-res1);
		printf("0->");
		for(i=1;i<nowdep;i++)
		printf("%d->",ans[i]);
		printf("%d %d\n",ans[nowdep],res2);
		
	}
	return 0;
}


 

function copy-data([int]$startrow, [int]$startcol, [int]$endrow, [int]$endcol, [string]$pat, [string]$file, [int]$sheetfrom, [int]$sheetto) { $excel = New-Object -ComObject Excel.Application $excel.Visible = $false $wb = $excel.Workbooks.Open($file) $wsfrom = $wb.Sheets.Item($sheetfrom) $wsto = $wb.Sheets.Item($sheetto) $sr = $wsfrom.Range($wsfrom.Cells.Item($startrow, $startcol), $wsfrom.Cells.Item($endrow, $endcol)) $fc = $sr.Find($pat) if ($fc -ne $null) { $rown = $fc.Row $dsr = $wsto.Range($wsto.Cells.Item($rown, $startcol), $wsto.Cells.Item($rown + ($endrow - $startrow), $endcol)) $dsr = $dsr.Resize($sr.Rows.Count, $sr.Columns.Count) $sr.Copy() $dsr.PasteSpecial(-4104) } $excel.DisplayAlerts = $false $wb.Close($true) [Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null } $path = $PWD.Path $file = "$path\a.xlsx" # 将sheet1中第1行到第4行、第2列到第9列的数据复制到sheet2中 copy-data -startrow 1 -startcol 2 -endrow 4 -endcol 9 -pat 1009 -file $file -sheetfrom 1 -sheetto 2 # 将sheet1中第6行到第8行、第2列到第9列的数据复制到sheet2中 copy-data -startrow 6 -startcol 2 -endrow 8 -endcol 9 -pat 1018 -file $file -sheetfrom 1 -sheetto 2 # 将sheet1中第10行到第11行、第2列到第9列的数据复制到sheet2中 copy-data -startrow 10 -startcol 2 -endrow 11 -endcol 9 -pat 1023 -file $file -sheetfrom 1 -sheetto 2 这个是搜索sheet1中关键词吗,我现在要搜索sheet2中关键词 得到行信息后再把sheet1指定内容复制到sheet2指定区域,怎么修改呢
最新发布
05-19
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值