状态压缩dp
![]() |
|
Figure 1 | Figure 2 |
A police unit has dealt with a number of situations where they need to search multiple sites as rapidly as possible with a small group of officers. Figures 1 and 2 are diagrams for two situations. Sites to search are labeled with capital letters. The site labeled A is the common starting point. Some of these locations have connecting paths. Assume each connecting path takes one unit of time to traverse, and individual sites take no time for a visual search.
Consider Figure 1. If there are 3 or more officers it takes only one unit of time to search. Different officers follow paths AB, AC, and AD. If there are two officers, the complete search will take two time units. For example one officer could follow the path ABC and the other AD.
Consider Figure 2. If there were 3 officers, they could follow paths ABC, ABD, and AEAF and take 3 units of time. With 2 officers they could follow paths ABCBD and AEAF, and take 4 units of time.
These are simple enough examples to figure out by hand. For more complicated arrangements they want your programming help.
Input
The input will consist of 1 to 25 data sets, followed by a line containing only 0.
A dataset is a single line starting with blank separated positive integers s n p, where s is the number of sites to search, n is the number of officers, and p is the number of connecting paths between search sites. Limits are 2 ≤ s ≤ 10, 1 ≤ n ≤ 4, and p ≤ 20. The rest of the line contains p pairs of capital letters, indicating paths between sites, each preceded by a blank. Sites are labeled with the first s capital letters. All sites will be connected by some sequence of connecting paths. The two letters in each letter pair will be in increasing alphabetical order. No letter pair will be repeated.
Output
here is one line of output for each data set, containing only the minimum search time for n officers starting at site A.
Take some care with your algorithm, or else your solution may take too long.
The sample input data sets correspond to the scenarios discussed.
Sample Input
Sample Output
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[1050][10],f[20][20];
int a[1050],b[1050],c[1050];
int oo=1000000000;
void floyd(int n)
{
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(f[i][j]>f[i][k]+f[k][j]) f[i][j]=f[i][k]+f[k][j];
for(int t=0;t<1050;t++)
a[t]=b[t]=oo;
}
int min(int x,int y)
{
return x<y? x:y;
}
int max(int x,int y)
{
return x>y? x:y;
}
int main()
{
int s,n,p,i,j,k;
char str[3];
while(scanf("%d",&s)!=EOF){
if(!s) break;
scanf("%d%d",&n,&p);
for(i=0;i<s;i++){
for(j=0;j<s;j++)
f[i][j]=oo;
f[i][i]=0;
}
while(p--){
scanf("%s",str);
f[str[0]-'A'][str[1]-'A']=f[str[1]-'A'][str[0]-'A']=1;
}
floyd(s);//用floy算出s多源顶点到其他点的距离
for(i=0;i<(1<<s);i++)
for(j=0;j<s;j++)
dp[i][j]=oo;
for(i=1;i<s;i++)
dp[1<<(i-1)][i]=f[0][i];//A点到其他点的距离
for(i=1;i<(1<<(s-1));i++)这个感觉像一个完全背包,就是有一个人走的到情况的最优解
for(j=1;j<s;j++)
if(i&(1<<(j-1))){
for(k=1;k<s;k++){
if(i&(1<<(k-1))) continue;
dp[i|(1<<(k-1))][k]=min(dp[i|(1<<(k-1))][k],dp[i][j]+f[j][k]);
}
}
for(i=1;i<(1<<(s-1));i++){
for(j=1;j<s;j++)
a[i]=b[i]=min(a[i],dp[i][j]);
}
while(n>1) //相当于矩阵乘法,乘n次代表n个人走的最优解
{
memcpy(c,a,sizeof(a)); //c[i] 和 a[i] 相当于一个滚动数组
for(i=0;i<(1<<(s-1));i++)
a[i]=b[i];
for(i=1;i<(1<<(s-1));i++)
for(j=1;j<(1<<(s-1));j++)
{
a[i|j]=min(a[i|j],max(b[i],c[j]));
}
n--;
}
printf("%d\n",a[(1<<(s-1))-1]);
}
return 0;
}
1175: A Tour Around Hangzhou
Time Limit: 2 Sec Memory Limit: 128 MBSUBMIT: 84 Solved: 22
[SUBMIT][STATUS]
Description
swimming来到杭州旅行,杭州是个美丽的城市,有很多美丽的景点.但让他头痛的是这些景点之间都有很长的距离,swimming决定选择便宜快捷的公交作为交通工具.杭州的公交网也十分复杂,不同的景点之间要转很多次公交才能到达,已知这些公交都只能站点上下车,并且相同的两个站点之间可能会有多班公交车.swimming想让你帮他设计一条旅游线路,花最少的钱旅游完所有的景点,最后回到出发地.
Input
输入有多组案例.
Output
如果swimming能旅游完所有的景点并且最后回到出发地,输出swimming坐公交旅行的最低花费;如果不能,输出"What a pity"(不加引号).对于每个案例,输出占一行.
Sample Input
Sample Output
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio>
#include<string.h>
#include<queue>
#include<algorithm>
#include <iostream>
#define MAXE 100005
#define MAXN 10005
#define INF 0x3fffffff
typedef long long ll;
using namespace std;
struct edge{
int v, w, n;
}e[MAXE*2];
int n, m, k, view[15];
int first[MAXN],es;
int map[16][16], d[15][40000],ans;
ll full;
int inq[MAXN], dis[MAXN];
void addedge(int u, int v, int w){
e[es].v = v;
e[es].w = w;
e[es].n = first[u];
first[u] = es++;
}
void spfa(int st){
queue<int> q;
for (int i = 0; i < n; i++) {
inq[i] = 0;
dis[i] = (i == st ? 0 : INF);
}
q.push(st);
while (!q.empty()) {
int u = q.front();
q.pop();
inq[u] = 0;
for (int i = first[u]; i != -1; i = e[i].n) {
int v = e[i].v;
if (dis[v] > dis[u] + e[i].w) {
dis[v] = dis[u] + e[i].w;
if (!inq[v]) {
inq[v] = 1;
q.push(v);
}
}
}
}
}
int dfs(int p, ll stat){
if (d[p][stat] != -1) return d[p][stat];
if (stat == full) return d[p][stat] = map[p][0];
int ans = INF, tmp;
for(int i = 1; i <= k; i++){
if ((stat&((ll)1<<i)) == 0) {
tmp = dfs(i, stat ^ (1 << i));
if(tmp + map[p][i] < ans)ans = tmp + map[p][i];
}
// cout<<ans<<endl;
}
return d[p][stat] = ans;
}
int main(){
//freopen("F.in","r",stdin);
//freopen("F.out","w",stdout);
while (scanf("%d%d%d", &n, &m, &k)!=EOF) {
memset(first, -1, sizeof first);
es=0;
int ts, te, tv;
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &ts, &te, &tv);
addedge(ts, te, tv);
addedge(te, ts, tv);
}
for (int i = 1; i <= k; i++) {
scanf("%d", &view[i]);
}
scanf("%d", &view[0]);
memset(map, -1, sizeof map);
int hasway = 1;
for (int i = 0; i <= k && hasway; i++) {
spfa(view[i]);
for (int j = 0; j <=k && hasway; j++){
map[i][j] = dis[view[j]];
if (map[i][j] == INF) hasway = 0;
}
}
if (!hasway) {
printf("What a pity\n");
} else {
full=((ll)1<<(k+1))-2;
for(int i=0;i<=k;i++)for(ll j=0;j<=full;j++) d[i][j]=-1;
printf("%d\n",dfs(0, 0));
}
}
return 0;
}