• zoj 1232 Adventure of Super Mario


    已知一个无向图,有村庄节点a个,有城堡节点b个,1到a表示村庄,a+1到a+b表示城堡,求第一个村庄节点到最后一个城堡节点的最短距离。如果某一段路径长度小于等于L且中间经过的节点(不包括两端)均是村庄类型,则可以穿一种神奇的靴子瞬间移动到那里,靴子只能在节点上使用或停止,靴子只能用K次

     

    设共n个节点,对于如何使用这k次机会是一个动态规划问题,dp[ i ][ j ]表示从村庄1经过标号小于i的路径并使用j次穿靴子的机会到达点i的最短距离,则dp[ n ][ k ]为该问题最终结果,则状态转移方程为dp[ i ][ j ] = min( min ( dp[ k ][ j-1 ],dp[ k ][ j ] + dist[ k ][ i ] ) ),其中1<=k<i,dist数组表示最短路径。

    使用该方程还需知道哪些节点之间可以使用靴子直接转移,在floyd计算过程中判断即可。

    #include <stdio.h>
    #include <string.h>
    #define INF 10000
    int dist[110][110],mark[110][110],dp[110][20];  /*mark[i][j]为1表示从i到j可以使用靴子,为0则不可以,dist为最短路径数组*/       
    int n,a,b,m,l,k;
    int min(int a,int b)
    {
    	if(a>b)
    		return b;
    	else
    		return a;
    }
    void floyd()
    {
    	int i,j,q;
    	for(q=1;q<=n;q++)
    	{
    		for(i=1;i<=n;i++)
    		{
    			for(j=1;j<=n;j++)
    			{
    				if(q==i||q==j)
    					continue;
    				if(dist[i][j]>dist[i][q]+dist[q][j])
    					dist[i][j]=dist[i][q]+dist[q][j];
    				if(dist[i][j]<=l&&q<=a)    /*以节点q为中间节点,前a个是村庄,所以只要小于l即可,q大于a后,添                                                              加的中间节点是城堡,所以不可以直接到达*/
    					mark[i][j]=1;
    			}
    		}
    	}
    }
    
    void dynamic()
    {
    	int i,j,q,min1=INF;
    	for(i=1;i<=n;i++)
    		dp[i][0]=dist[1][i];
    	for(i=0;i<=k;i++)
    		dp[1][i]=0;
    	for(i=2;i<=n;i++)
    	{
    		for(j=1;j<=k;j++)
    		{
    			min1=INF;
    			for(q=1;q<i;q++)
    			{
    				if(mark[q][i]==1)
    					min1=min(min1,dp[q][j-1]);
    				min1=min(min1,dp[q][j]+dist[q][i]);
    			}
    			dp[i][j]=min1;
    		}
    	}
    }
    			
    	
    int main()
    {
    	int t,i,j,q;
    	int x,y,w;
    	scanf("%d",&t);
    	for(i=0;i<t;i++)
    	{
    		memset(mark,0,sizeof(mark));
    		scanf("%d%d%d%d%d",&a,&b,&m,&l,&k);
    		n=a+b;
    		for(j=1;j<=n;j++)
    			for(q=1;q<=n;q++)
    				dist[j][q]=INF;
    		for(j=0;j<m;j++)
    		{
    			scanf("%d%d%d",&x,&y,&w);
    			dist[x][y]=dist[y][x]=w;
    			if(w<=l)
    				mark[x][y]=mark[y][x]=1;
    		}
    		floyd();
    		dynamic();
    		printf("%d
    ",dp[n][k]);
    	}
    	return 0;
    }
    


     

  • 相关阅读:
    学会使用控件之comboxBox in asp.net 从简单开始(五)
    学会使用控件从简单开始(四)
    关于SQL计算差值的问题
    关于CSS3的一些代码
    显式实现的接口成员从简单开始(三)
    网页选项卡(TAB)今天晚上搞了一晚上这个
    关于页面刷新
    委托和匿名方法从简单开始(一)
    短信监听器
    android中handler处理message小例子
  • 原文地址:https://www.cnblogs.com/vermouth/p/3710227.html
Copyright © 2020-2023  润新知