2020暑期培训 Day3
思路:
我们肯定希望在余额大于$5$元并且最接近的时候去买那个最贵的
所以问题就转化为只有$m-5$元,在前$n-1$低的物品中尽可能话更多的钱买
这就转化为一个裸的$0-1$背包问题了
#include<iostream> #include<algorithm> #include<queue> #include<cstring> using namespace std; typedef long long ll; int a[1005],dp[1005],n,m; int main() { while(cin>>n&&n){ for(int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+1+n); cin>>m; if(m<5) cout<<m<<endl; else{ memset(dp,0,sizeof(dp)); for(int i=1;i<n;i++) for(int j=m-5;j>=a[i];j--) dp[j]=max(dp[j],dp[j-a[i]]+a[i]); cout<<m-dp[m-5]-a[n]<<endl; } } return 0; }
B - 数塔 (HDU - 2084) DP
思路:
DP入门题
#include<iostream> #include<algorithm> using namespace std; const int maxn=110; int dp[maxn][maxn],a[maxn][maxn]; int main() { int t,n; cin>>t; while(t--){ cin>>n; for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) cin>>a[i][j]; int ans=dp[1][1]=a[1][1]; for(int i=2;i<=n;i++){ for(int j=1;j<=i;j++){ dp[i][j]=max(dp[i-1][j]+a[i][j],dp[i-1][j-1]+a[i][j]); if(i==n) ans=max(dp[i][j],ans); } } cout<<ans<<endl; } return 0; }
C - Bridging signals (HDU - 1950) LIS优化
思路:
化简题意就是求一个LIS,但是由于数据比较大,需要用数据结构或者二分来进行优化
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #define lowbit(x) (x&(-x)) using namespace std; const int maxn=100100; int n=0,len; int a[maxn],mx[maxn]; void add(int x,int val) { while(x<=maxn){ mx[x]=max(mx[x],val); x+=lowbit(x); } } int query(int x) { int ans=0; while(x>=1){ ans=max(mx[x],ans); x-=lowbit(x); } return ans; } int main() { int t,n; cin>>t; while(t--){ memset(mx,0,sizeof(mx)); cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; int ans=0; for(int i=1;i<=n;i++){ int x=query(a[i])+1; add(a[i],x); ans=max(ans,x); } cout<<ans<<endl; } return 0; }
D - 反恐训练营 (HDU - 1243)
思路:
最长公共子序列变形
#include<iostream> #include<algorithm> #include<map> #include<cstring> using namespace std; const int maxn=2005; map<char,int> m; string s,a,b; int dp[maxn][maxn]; int main() { int n,x; while(scanf("%d",&n)!=EOF){ memset(dp,0,sizeof(dp)); m.clear(); cin>>s; for(int i=0;i<n;i++){ cin>>x; m[s[i]]=x; } cin>>a>>b; int len1=a.length(); int len2=b.length(); for(int i=0;i<len1;i++){ for(int j=0;j<len2;j++){ if(a[i]==b[j]) dp[i+1][j+1]=dp[i][j]+m[a[i]]; else dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]); } } cout<<dp[len1][len2]<<endl; } return 0; }
E - Rescue Haibara (Gym - 101778E) 结构体排序
思路:
按照题意对各个安全屋进行排序就好了
#include<iostream> #include<algorithm> using namespace std; const int maxn=510; struct node{ int d, m, num; }a[maxn]; int cmp(struct node xx, struct node yy) { if(xx.d!=yy.d) return xx.d<yy.d; else if(xx.m!=yy.m) return xx.m>yy.m; else if(xx.num!=yy.num) return xx.num<yy.num; return -1; } int main() { int t,n,x,y,u,v; cin>>t; while(t--){ int h=0; cin>>n>>x>>y; for(int i=0;i<n;i++){ cin>>u>>v; if(u<=x&&v>=y){ a[h].num = i+1, a[h].d = u, a[h++].m = v; } } sort(a, a+h, cmp); if(h==0) printf("-1\n"); else printf("%d\n",a[0].num); } return 0; }
F - Position in Fraction (CodeForces - 900B) 模拟
思路:
模拟除法的过程,注意及时跳出
#include<iostream> #include<algorithm> using namespace std; typedef long long LL; const int maxn = 1e5+1000; int i,pos=-1,c; int main() { int fz,fm,i=0; cin>>fz>>fm>>c; while(1){ i++; fz=fz*10; if(fz/fm==c){ pos=i; break; } fz=fz%fm; if(i>=100005) break; } cout<<pos; return 0; }
G - Merge Equal Elements (CodeForces - 926E) 模拟
思路:
按照题意直接模拟
#include<iostream> #include<algorithm> using namespace std; const int maxn=1e6+5; int a[maxn]; int main() { int n,x,k; cin>>n; for(int i=1;i<=n;i++){ cin>>x; while(x==a[k]){ k--; x++; } k++; a[k]=x; } cout<<k<<endl; for(int i=1;i<=k;i++) cout<<a[i]<<" "; return 0; }
H - Data Center Maintenance (CodeForces - 949C) Tarjan缩点
思路:
对于一个数据的两台机器宕机时间$t1,t2$,如果$t2=(t1+1)%h,t1=(t2+1)%h$,那么他们就会有影响,我们就应该给他们连一条边
这样建图之后,我们用$tarjan$进行缩点,就成为了一张$DAG$图,答案就为入度为$0$,并且大小最小的联通块
#include<iostream> #include<algorithm> #include<vector> using namespace std; const int maxn=1e5+10; vector<int> a[maxn]; int tot=0,t=0,k=0; int dfs[maxn],low[maxn],stack[maxn],flag[maxn],color[maxn],cnt[maxn],in[maxn],tim[maxn]; void tarjan(int x) { dfs[x]=low[x]=++tot; stack[++k]=x; flag[x]=1; for(int i=0;i<a[x].size();i++){ if(!dfs[a[x][i]]){ tarjan(a[x][i]); low[x]=min(low[x],low[a[x][i]]); } else if(flag[a[x][i]]) low[x]=min(low[x],dfs[a[x][i]]); } if(dfs[x]==low[x]){ t++; do{ color[stack[k]]=t,cnt[t]++; flag[stack[k--]]=0; }while(x!=stack[k+1]); } } int main() { int n,m,h,u,v; scanf("%d%d%d",&n,&m,&h); for(int i=1;i<=n;i++) scanf("%d",&tim[i]); for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); if(tim[u]==(tim[v]+1)%h) a[u].push_back(v); if(tim[v]==(tim[u]+1)%h) a[v].push_back(u); } for(int i=1;i<=n;i++) if(!dfs[i]) tarjan(i); for(int i=1;i<=n;i++){ for(int j=0;j<a[i].size();j++){ int v=a[i][j]; if(color[i]!=color[v]) in[color[v]]++; } } cnt[0]=n+1; int ans=0; for(int i=1;i<=t;i++) if(cnt[i]<cnt[ans]&&in[i]==0) ans=i; cout<<cnt[ans]<<endl; for(int i=1;i<=n;i++) if(color[i]==ans) cout<<i<<" "; return 0; }