链接: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; }
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; }