• 1018 Public Bike Management (30分) (迪杰斯特拉+dfs)


    思路就是dijkstra找出最短路,dfs比较每一个最短路。
    dijkstra可以找出每个点的前一个点, 所以dfs搜索比较的时候怎么处理携带和带走的数量就是关键,考虑到这个携带和带走和路径顺序有关,所以可以用下面的写法,看代码就可以了。
    最开始的时候是想用一个偏动态规划的写法做,但是因为题目的显示,既要带去的车数量最少,又要求从一个点带走的车数量最少,所以如果过动规的话,对于一个点的多个最短路,就会选择带去数量最少,带走车数最少的路径,但是如果这个点后面的点的车辆数少一标准量的一半的话,前面带的是最少的,这样相当于携带的车的数量就多了,这样就矛盾了。
    当时挺纠结的,因为只写过一道类型的题,还是用动规的写法写的,那个权值只有两个,也是pat的题,这个主要是权值矛盾了, 所以不能用动规的思想写。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=505;
    const int INF=0x3f3f3f3f;
    
    int g[maxn][maxn];
    vector<int> pre[maxn];
    int C,N,M,SP;
    int vis[maxn],num[maxn],d[maxn];
    
    void dijkstra()
    {
    	d[0]=0;
    
    	for (int i=0;i<N;i++) {
    		int u=-1,tmp=INF;
    		for (int j=0;j<=N;j++) {
    			if (!vis[j]&&d[j]<tmp) {
    				tmp=d[j];
    				u=j;
    			}
    		}
    		if (u==-1) break;
    		vis[u]=1;
    		for (int j=0;j<=N;j++) {
    			if (j==u) {
    				continue;
    			}
    			if (d[u]+g[u][j]<d[j]) {
    				d[j]=d[u]+g[u][j];
    				pre[j].clear();
    				pre[j].push_back(u);
    			}
    			else if (d[u]+g[u][j]==d[j]) {
    				pre[j].push_back(u);
    			}
    		}
    	}
    }
    
    int path[maxn],acnt=0;
    int ansn=INF,anst=INF,ansp[maxn];
    void dfs(int u,int need,int take,int cnt)
    {
    	path[cnt]=u;
    	if (u==0) {
    		// for (int i=0;i<cnt;i++) {
    		// 	printf("%d ",path[i]);
    		// }
    		// puts("");
    		// printf("need %d take %d
    ",need,take);
    		if (need<ansn) {
    			ansn=need;
    			anst=take;
    			acnt=cnt;
    			for (int i=0;i<cnt;i++) {
    				ansp[i]=path[i];
    			}
    			
    		}
    		else if (need==ansn) {
    			if (take<anst) {
    				anst=take;
    				acnt=cnt;
    				for (int i=0;i<cnt;i++) {
    					ansp[i]=path[i];
    				}
    			}
    		}
    		return ;
    	}
    	if (num[u]==C/2) {}
    	else if (num[u]>C/2) {
    		if (need>0) {
    			if (num[u]-C/2>=need) {
    				take+=num[u]-C/2-need;
    				need=0;
    			}
    			else need-=num[u]-C/2;
    		}
    		else take+=num[u]-C/2;
    	}
    	else need+=C/2-num[u];
    
    	int sz=pre[u].size();
    	for (int i=0;i<sz;i++) {
    
    		dfs(pre[u][i],need,take,cnt+1);
    	}
    }
    
    int main()
    {
    	// freopen("in.txt","r",stdin);
    	scanf("%d%d%d%d",&C,&N,&SP,&M);
    	for (int i=1;i<=N;i++) {
    		scanf("%d",&num[i]);
    	}
    	
    	memset(g,INF,sizeof(g));
    	for (int i=0;i<=N;i++) {
    		g[i][i]=0;
    		d[i]=INF;
    	}
    
    	int u,v,c;
    	for (int i=0;i<M;i++) {
    		scanf("%d%d%d",&u,&v,&c);
    		g[u][v]=c;
    		g[v][u]=c;
    	}
    	dijkstra();
    	// for (int i=1;i<=N;i++) {
    	// 	printf("%d ",d[i]);
    	// }
    	// puts("");
    	// for (int i=1;i<=N;i++) {
    	// 	printf("%d:
    ",i);
    	// 	for (int j=0;j<pre[i].size();j++) {
    	// 		printf("%d ",pre[i][j]);
    	// 	}
    	// 	printf("
    ");
    	// }
    	dfs(SP,0,0,0);
    	printf("%d %d",ansn,0);
    	for (int i=acnt-1;i>=0;i--) {
    		printf("->%d",ansp[i]);
    	}
    	printf(" %d
    ",anst);
    	return 0;
    }
    
  • 相关阅读:
    LintCode-乱序字符串
    LintCode-字符串查找
    LintCode-比较字符串
    LintCode-两个字符串是变位词
    LintCode-不同的子序列
    View(视图)——AutoCompleteTextView、Spinner
    View(视图)——GridView(点击长按删除图片)
    给图片下加字符
    View(视图)——ListView:BaseAdapter、SimpleCursorAdapter
    View(视图)——ListView:ArrayAdapter、SimpleAdapter
  • 原文地址:https://www.cnblogs.com/xyqxyq/p/12328852.html
Copyright © 2020-2023  润新知