hdu 5418 题 解

At first glance this question, wow, this is not a problem I just finished it? Flood problem! then



This problem is surface water, in fact, a little pit.

The meaning of problems

After seeking $ 1 - n $ (can not miss) and shortest path back to the $ 1 $.

Before looking at this question we can look at this problem

The shortest Hamilton Road

We want this question is required for each point do not leak through and ultimately to $ n-1 $ we see the data range, it can be directly shaped pressure DP, the enumeration state.

Since the subject has been given the shortest, can be calculated directly

#include<bits/stdc++.h>
using namespace std;
int n,a[30][30];
int f[1100000][30];
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;++i){
        for(int j=0;j<n;++j){
            scanf("%d",&a[i][j]);
        }
    }
    memset(f,0x3f,sizeof(f));
    f[1][0]=0;
    for(int i=1;i<(1<<n);++i){//状态
        for(int j=0;j<n;++j){//终点
            if((i>>j)&1){
                for(int k=0;k<n;++k){//起点
                    if(((i>>k)&1)&&a[j][k]){//保证有路相通
                        f[i][j]=min(f[i][j],f[i^(1<<j)][k]+a[k][j]);//找没能达到j的
                    }
                }
            }
        }
    }   
    printf("%d",f[(1<<n)-1][n-1]);//最后在n-1
    return 0;
}

So we come back to this question, which gives each side a point, the last to go through, and return, think carefully, is not more than a shortest do? Direct run again $ floyd $ enumeration end return is not good enough?

Then I wrote the code for

#include<bits/stdc++.h>
using namespace std;
const int INF=1<<30;
int n,m,T,dis[20][20];
int f[(1<<20)][20];
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        if(n==1){
            printf("0\n");
            continue;
        } 
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j){
                if(i==j) dis[i][j]=0;
                else dis[i][j]=INF;
            }
        }
        for(int i=1;i<=m;++i){
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            dis[x][y]=min(dis[x][y],z);
            dis[y][x]=dis[x][y];
        }
        for(int k=1;k<=n;++k){
            for(int i=1;i<=n;++i){
                for(int j=1;j<=n;++j){
                    if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j];
                }
            }
        }
        memset(f,0x3f,sizeof(f));
        f[1][1]=0;
           for(int i=1;i<(1<<n);++i){
               for(int j=1;j<=n;++j){
                   if((i>>(j-1))&1){
                       for(int k=1;k<=n;++k){
                           if(((i>>(k-1))&1)&&(dis[j][k]!=INF)){
                               f[i][j]=min(f[i][j],f[i^(1<<(j-1))][k]+dis[j][k]);
                           }
                       }
                   }
               }
           }
           int ans=1<<30;
           for(int i=1;i<=n;++i){
               ans=min(ans,f[(1<<n)-1][i]+dis[i][1]);
           }printf("%d\n",ans);
    }
    return 0;
}

Then RE, later asked a music teacher, found that the problem will be self-loop

if(n==1){
    printf("0\n");
    continue;
}

This is the crux of the problem, not directly $ continue $ because there is no time coming back side, will lead to RE.

Then I wrote a bit

#include<bits/stdc++.h>
using namespace std;
const int INF=1<<30;
int n,m,T,dis[20][20];
int f[(1<<20)][20];
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        for(int i=0;i<=n;++i){
            for(int j=0;j<=n;++j){
                if(i==j) dis[i][j]=0;
                else dis[i][j]=INF;
            }
        }
        for(int i=1;i<=m;++i){
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            dis[x][y]=min(dis[x][y],z);
            dis[y][x]=dis[x][y];
        }
        if(n==1){
            printf("0");
            continue;
        }
        for(int k=1;k<=n;++k){
            for(int i=1;i<=n;++i){
                for(int j=1;j<=n;++j){
                    if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j];
                }
            }
        }
        memset(f,0x3f,sizeof(f));
        f[1][1]=0;
           for(int i=1;i<(1<<n);++i){
               for(int j=1;j<=n;++j){
                   if((i>>(j-1))&1){
                       for(int k=1;k<=n;++k){
                           if(((i>>(k-1))&1)&&(dis[k][j]!=INF)){
                               f[i][j]=min(f[i][j],f[i^(1<<(j-1))][k]+dis[k][j]);
                           }
                       }
                   }
               }
           }
           int ans=1<<30;
           for(int i=1;i<=n;++i){
               ans=min(ans,f[(1<<n)-1][i]+dis[i][1]);
           }printf("%d\n",ans);
    }
    return 0;
}

$ Wa $ hear a sound, I looked behind his own solution to a problem, the idea that no problem, looking at it the maximum value is defined as $ 0x3f3f3f3f $ I changed, then it passed? ?

The reason is not the same as the maximum two errors led to $ dp $ process will appear, and finally I changed

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int n,m,T,dis[20][20];
int f[(1<<20)][20];
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        for(int i=0;i<=n;++i){
            for(int j=0;j<=n;++j){
                if(i==j) dis[i][j]=0;
                else dis[i][j]=INF;
            }
        }
        for(int i=1;i<=m;++i){
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            dis[x][y]=min(dis[x][y],z);
            dis[y][x]=dis[x][y];
        }
        if(n==1){
            printf("0\n");
            continue;
        }
        for(int k=1;k<=n;++k){
            for(int i=1;i<=n;++i){
                for(int j=1;j<=n;++j){
                    if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j];
                }
            }
        }
        memset(f,0x3f,sizeof(f));
        f[1][1]=0;
           for(int i=1;i<(1<<n);++i){
               for(int j=1;j<=n;++j){
                   if((i>>(j-1))&1){
                       for(int k=1;k<=n;++k){
                           if(((i>>(k-1))&1)&&(dis[k][j]!=INF)){
                               f[i][j]=min(f[i][j],f[i^(1<<(j-1))][k]+dis[k][j]);
                           }
                       }
                   }
               }
           }
           int ans=INF;
           for(int i=1;i<=n;++i){
               ans=min(ans,f[(1<<n)-1][i]+dis[i][1]);
           }printf("%d\n",ans);
    }
    return 0;
}

Then finally $ AC $, in fact, this question itself is not difficult, mainly dealing in some detail, and exposed in multiple sets of data it is clear that the question usually write a lot of details still have to pay attention.

Guess you like

Origin www.cnblogs.com/donkey2603089141/p/11736091.html