2020暑期培训 Day3

A - 饭卡 (HDU - 2546)  0-1背包

思路:

我们肯定希望在余额大于$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;
}
View Code

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;
}
View Code

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;
 }
View Code

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;
 }
View Code

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;
}
View Code

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;
}
View Code

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;
 }
View Code

 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;
 }
View Code

 

posted @ 2020-07-03 21:57  overrate_wsj  阅读(194)  评论(0编辑  收藏  举报