1、
NKOJ 3707 送外卖
时间限制 : - MS 空间限制 : 65536 KB
评测说明 : 时限2000ms
问题描述
有一个送外卖的,他手上有n份订单,他要把n份东西,分别送达n个不同的客户的手上。n个不同的客户分别在1~n个编号的城市中。送外卖的从0号城市出发,然后n个城市都要走一次(一个城市可以走多次),最后还要回到0点(他的单位),请问最短时间是多少。现在已知任意两个城市的直接通路的时间。
输入格式
第一行一个正整数n (1<=n<=15)
接下来是一个(n+1)*(n+1)的矩阵,矩阵中的数均为不超过10000的正整数。矩阵的i行j列表示第i-1号城市和j-1号城市之间直接通路的时间。当然城市a到城市b的直接通路时间和城市b到城市a的直接通路时间不一定相同,也就是说道路都是单向的。
输出格式
一个正整数表示最少花费的时间
样例输入
3
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
样例输出
8
来源 East Central North America 2006
思路:因为一个城市可以经过多次,所以先Floyd。
#include<cstdio>
#include<iostream>
using namespace std;
const int need=18;
int a[need][need],f[1<<16][need];
int main()
{
int n;scanf("%d",&n);
int s=(1<<n+1)-1;
for(int j,i=0;i<=n;i++)
for(j=0;j<=n;j++)
scanf("%d",&a[i][j]);
for(int i,j,k=0;k<=n;k++)
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
for(int j,i=1;i<=s;i++)
for(j=0;j<=n;j++) f[i][j]=1e9;
f[1][0]=0;
int u,v,t;
for(int i=1;i<=s;i++)
for(u=0;u<=n;u++)
if((i>>u)&1)
for(v=0;v<=n;v++)
if(!((i>>v)&1))
{
t=i|(1<<v);
f[t][v]=min(f[t][v],f[i][u]+a[u][v]);
}
int ans=1e9;
for(int i=1;i<=n;i++)
{
ans=min(ans,f[s][i]+a[i][0]);
}
printf("%d",ans);
}
2、****NKOJ 1752 传球游戏
时间限制 : 10000 MS 空间限制 : 65536 KB
问题描述
n个人在做传球的游戏,编号为1-n。
游戏规则是这样的:开始时球可以在任意一人手上,他可把球传递给其他人中的任意一位;下一个人可以传递给未接过球的任意一人。
即球只能经过同一个人一次,而且每次传递过程都有一个代价;不同的人传给不同的人的代价值之间没有联系;
求当球经过所有n个人后,整个过程的最小总代价是多少。
输入格式
第一行为n,表示共有n个人(16>=n>=2);
以下为n*n的矩阵,第i+1行、第j列表示球从编号为i的人传递到编号为j的人所花费的代价,特别的有第i+1行、第i列为-1(因为球不能自己传给自己),其他数据均为正整数(<=10000)。
输出格式
一个数,为最小的代价总和。
样例输入
样例输入1:
2
-1 9794
2724 –1
样例输入2:
4
-1 4551 3763 4873
4465 -1 9323 2204
705 2102 -1 333
9264 5206 2596 -1
样例输出
样例输出1:
2724
样例输出2:
5505
思路:
因为是单向边,所以可能选择不同起点得到的最短路径不同,理论上应该统计所有以节点为起点的最小值
但可以增加虚拟节点来减少代码复杂度:把0号看做与所有点距离为零的虚拟节点,只用讨论从0出发,经过所有点的最短距离就好了。
#include<cstdio>
#include<iostream>
using namespace std;
const int need=18;
int a[need][need],f[1<<17][need];
int main()
{
int n;scanf("%d",&n);
int s=(1<<n+1)-1;
for(int j,i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
if(i==j) a[i][j]=0;
}
for(int j,i=1;i<=s;i++)
for(j=0;j<=n;j++) f[i][j]=1e9;
f[1][0]=0;
int u,v,t;
for(int i=1;i<=s;i++)
for(u=0;u<=n;u++)
if((i>>u)&1)
for(v=0;v<=n;v++)
if(!((i>>v)&1))
{
t=i|(1<<v);
f[t][v]=min(f[t][v],f[i][u]+a[u][v]);
}
int ans=1e9;
for(int i=0;i<=n;i++)
{
ans=min(ans,f[s][i]);
}
printf("%d",ans);
}