• 最小代价


    题目内容

    n个人在做传递物品的游戏,编号为1-n。

    游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位;下一个人可以传递给未接过物品的任意一人。

    即物品只能经过同一个人一次,而且每次传递过程都有一个代价;不同的人传给不同的人的代价值之间没有联系;

    求当物品经过所有n个人后,整个过程的总代价是多少。
    传送

    题解

    状态压缩模板,用f[i][j]表示在i状态时最后填的一个是j。
    转移方程
    f[i][j]=min(f[i-(1<<j)][k]+cost[k][j],f[i][j])
    k表示从k点转移到了j位置,所以要求j,k都应该是集合i中的元素。
    注意
    阶段应该是状态i而不是j
    所以循环要这样写
    for(i=1;i<=tot;i++)
    for(j=0;j<n;j++)
    if(i&(1<<j))
    for(k=0;k<n;k++)
    if((i&(1<<k))&&j!=k)
    f[i][j]=min(f[i-(1<<j)][k]+co[k][j],f[i][j]);

    反思

    先开始想的状态转移方程是在状态i时经过了j次传递,这样好像顺序有问题,所以错了;

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=17;
    long long  f[1<<N][N];
    int co[N][N],digit[1<<N],w[N][1<<N];
    int main()
    {
    //	freopen("cost.in","r",stdin);
    //	freopen("cost.out","w",stdout);
    	memset(f,127,sizeof(f));
    	int n;
    	scanf("%d",&n);	
    	int i,j,k,h;
    	long long minc=0x7fffffff;
    	for(i=0;i<n;i++)
    		for(j=0;j<n;j++)
    			scanf("%d",&co[i][j]);
    	int tot=(1<<n)-1;
    	for(i=0;i<n;i++)
    		f[1<<i][i]=0;
    	for(i=1;i<=tot;i++)
    		for(j=0;j<n;j++)
    			if(i&(1<<j))
    				for(k=0;k<n;k++)
    					if((i&(1<<k))&&j!=k)
    						f[i][j]=min(f[i-(1<<j)][k]+co[k][j],f[i][j]);
    	for(i=0;i<n;i++)
    		minc=min(minc,f[tot][i]);
    	printf("%lld
    ",minc);
    	return 0;
    }
  • 相关阅读:
    GTK+ 3.6.2 发布,小的 bug 修复版本
    RunJS 新增 Echo Ajax 测试功能
    Mozilla 发布 Popcorn Maker,在线创作视频
    Sina微博OAuth2框架解密
    Mina状态机State Machine
    Mozilla 发布 Shumway —— 纯JS的SWF解析器
    Code Browser 4.5 发布,代码浏览器
    ROSA 2012 "Enterprise Linux Server" 发布
    ltrace 0.7.0 发布,程序调试工具
    Artifactory 2.6.5 发布,Maven 扩展工具
  • 原文地址:https://www.cnblogs.com/2020pengxiyue/p/8119622.html
Copyright © 2020-2023  润新知