牛客算法周周练7-题解

链接:https://ac.nowcoder.com/acm/contest/5927#question

A - 收集纸片

题意:

在二维坐标中有$n$个点需要你依次到达并最后返回起点,求最短路程

思路:

典型的$TSP$旅行商问题,因为$n$最大只有$10$,所以我们可以用$DFS$遍历所有可能的情况,时间复杂度为$O(10!)$

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#define inf 0x3f3f3f3f
 using namespace std;
 typedef long long ll;
 int x,y,sx,sy,n,ans;
 int vis[11];
 struct node{
     int x,y;
 }a[11];
 void dfs(int cnt,int num,int dis)
 {
     if(cnt==n){
         ans=min(ans,dis+abs(a[num].x-sx)+abs(a[num].y-sy));
         return;
     }
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            int ret=dis+abs(a[num].x-a[i].x)+abs(a[num].y-a[i].y);
            vis[i]=1;
            dfs(cnt+1,i,ret);
            vis[i]=0;
        } 
    }
 }
 int main()
 {
     int t;
     cin>>t;
     while(t--){
         memset(vis,0,sizeof(vis));
         ans=inf;
         cin>>x>>y>>sx>>sy;
        cin>>n;    
        for(int i=1;i<=n;i++)
            cin>>a[i].x>>a[i].y;
        for(int i=1;i<=n;i++){
            vis[i]=1;
            dfs(1,i,abs(a[i].x-sx)+abs(a[i].y-sy));
            vis[i]=0;
        }
        cout<<"The shortest path has length "<<ans<<endl;
     }
     return 0;
 }
View Code

C -  Rabbit的工作(1)

题意:

一共有$n$天,如果连续工作第$i$天需要耗费精力$i$,同时根据安排你也可以休息,不消耗精力,在消耗精力小于等于$k$的情况下,问你最多能工作几天

思路:

定义$dp[i][j][k]$为,过去$i$天,当前已经连续工作$j$天,总计工作$k$天需要消耗的精力

如果选择休息则状态转移方程为$dp[i+1][0][k]=min(dp[i][j][k],dp[i+1][0][k])$

在可以工作的情况下,转态转移方程为$dp[i+1][j+1][k+1]=min(dp[i+1][j+1][k+1],dp[i][j][k]+(j+1))$

最后,因为内存限制,第一维可以用滚动数组节约空间

#include<algorithm>
#include<iostream>
#include<cstring>
#define inf 0x3f3f3f3f
 using namespace std;
 const int N=405;
 int dp[2][N][N];
 string s;
 int main()
 {
     int n,x,ans=0;
     cin>>n>>x;
     dp[0][0][0]=0;
     int now=0;
     cin>>s;
    for(int i=1;i<=n;i++){
        memset(dp[now^1],inf,sizeof(dp[now^1]));
        for(int j=0;j<i;j++){
            for(int k=j;k<i;k++){
                dp[now^1][0][k]=min(dp[now][j][k],dp[now^1][0][k]);
                if(s[i-1]=='1')
                    dp[now^1][j+1][k+1]=min(dp[now][j][k]+j+1,dp[now^1][j+1][k+1]);
            }
        }
        now^=1;
    }
    for(int i=0;i<=n;i++){
        for(int j=i;j<=n;j++){
            if(dp[now][i][j]<=x) 
                ans=max(ans,j);
        }
    }
    cout<<ans;
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/overrate-wsj/p/12983851.html