zoukankan      html  css  js  c++  java
  • 暑假的学习

    刷题时,刷到了阮一峰的博客,看了看感觉是个比较有想法的人,有兴趣可以百度一下

    先记录下今天的学习吧

    给一张图,从1点出发,要求是一次走完后,再求出这次中从1点到达各个点的总时间,其中每个点都有deadlinetime

    先是对这个图跑一遍floyd,让每个点都预处理一下,然后进行深搜,深搜的时候要注意剪枝

    最优性剪枝和可行性剪枝

    #include<bits/stdc++.h>
    using namespace std;
    int str[35][35];
    int n,ans,dd[35];
    int vis[35];
    int inf=0x3f3f3f3f;
    void floyd()
    {
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                str[i][j]=min(str[i][j],str[i][k]+str[k][j]);
            }
        }
    }
    void dfs(int s,int time,int total,int cnt)//time为到达某个点的时间//total为总时间,cnt剩余点数 
    {
        if(cnt==0)
        {
            ans=min(ans,total);
            return;
        }
         if (total+cnt*time >= ans) //后面的点的time肯定是越来越大的,假设都为time,最优性剪枝 
             return;
         
        
        for(int i=2;i<=n;i++)//这个循环和下面要分开写 ,这个是判断当前点s 的可行性剪枝 
        if(!vis[i]&&time+str[s][i]>dd[i]) return;//s到其他点有超时的,那么再从这点出发后不管怎样都可定超时 
        for(int i=2;i<=n;i++)
        {
            if(!vis[i])
            {
                vis[i]=1;
                dfs(i, time+str[s][i] , total+time+str[s][i], cnt-1);
                vis[i]=0;
            }
        }
    }
    int main()
    {
        while(~scanf("%d",&n))
        {
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    scanf("%d",&str[i][j]);
            for(int i=2;i<=n;i++) scanf("%d",&dd[i]);
            
            floyd();
            memset(vis,0,sizeof(vis));
            ans=inf;
            dfs(1,0,0,n-1);
            if(ans == inf )printf("-1
    ");
            else printf("%d
    ",ans);    
        }
    }

    双向bfs

    HDU - 3085 

    题意:erriye 梦见女友被困在迷宫里了,现在 erriye 需要去解救他的的女友 给出他女友和他的位置

    题意:迷宫里有两个ghost,每秒钟会分生出多个ghost占据在他2步之内的所有格子

    little erriye 每秒可以移动3步,grilfriend每秒可以移动一步

    ghost、erriye、grilfriend都只能上下左右移动(且人不能穿透墙壁,鬼魂可以)

    题意:人一旦与鬼魂占据同一格子,则被杀死

    题意:问:little erriye 最少需要多久才能解救其女友?(如果解救失败,输出-1)

    #include<bits/stdc++.h>
    using namespace std;
    
    int dx[]={0,0,1,-1};
    int dy[]={1,-1,0,0};
    
    char str[802][802];
    int vis[2][802][802];//标记路径 
    int n,m,step;
    struct node{
        int x,y;
    }ss,ee,z[2];
    queue<node>q[2];
    void init()
    {
        int cnt=0;
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            scanf("%s",str[i]);
            for(int j=0;j<m;j++)
            {
                if(str[i][j]=='M') ss.x=i,ss.y=j;
                else if(str[i][j]=='G') ee.x=i,ee.y=j;
                else if(str[i][j]=='Z') z[cnt].x=i,z[cnt++].y=j;
            }
        }
    }
    int judge(node b)
    {
        if(b.x<0||b.y<0||b.x>=n||b.y>=m||str[b.x][b.y]=='X')
        return 0;
        if(abs(b.x-z[0].x)+abs(b.y-z[0].y)<=2*step)//判断是否撞鬼
        return 0;
        if(abs(b.x-z[1].x)+abs(b.y-z[1].y)<=2*step)
        return 0;
        return 1;
    }
    int bfs(int w)
    {
        node now,next;
        int sum;
        sum=q[w].size();
        while(sum--)
        {
            now=q[w].front();
            q[w].pop();
            if(judge(now)==1)
            {
                for(int i=0;i<4;i++)
                {
                    next.x=now.x+dx[i];
                    next.y=now.y+dy[i];
                    
                    if(judge(next)==1&&vis[w][next.x][next.y]==0)
                    {
                        if(vis[w^1][next.x][next.y]==1)//解救成功条件是这条路是另一个人走过的 
                        return 1;
                        vis[w][next.x][next.y] = 1;
                        q[w].push(next);
                    }
                }
            }
        }
        return -1;
    }
    int solve()
    {
        while(!q[0].empty())q[0].pop();
        while(!q[1].empty()) q[1].pop();
        
        q[0].push(ss);
        q[1].push(ee);
        
        memset(vis,0,sizeof(vis));
        vis[0][ss.x][ss.y]=vis[1][ee.x][ee.y]=1;
        step=0;
        while((!q[0].empty())||(!q[1].empty()))
        {
            step++;
            if(bfs(0)==1) return step;
            if(bfs(0)==1) return step;
            if(bfs(0)==1) return step;
            if(bfs(1)==1) return step;
        }
        return -1;
    }
    int main()
    {
        int tt;
        cin>>tt;
        while(tt--)
        {
            init();
            cout<<solve()<<endl;
        }
        return 0;
    }

     hdu6383

    http://acm.hdu.edu.cn/showproblem.php?pid=6383

    题目大意:给你一堆数字,可以随便找两个,一个+1,一个-2,使最后形成的数列最大值和最小值相差为1,求最小值的最大值

    #include<bits/stdc++.h>
    using namespace std;
    long long a[10000020];
    int main()
    {
        long long t;
        scanf("%lld",&t);
        while(t--)
        {
            long long n;
            scanf("%lld",&n);
            long long l=0x3f3f3f3f,r=-1;
            for(int i=0;i<n;i++) {
                scanf("%lld",&a[i]);
                l=min(l,a[i]);
                r=max(r,a[i]);
            }
            long long mid=0,ans=-1;
            while(l<=r)//注意不要l<r会死循环 
            {
                mid=(l+r)>>1;
                long long up=0,down=0;
                for(int i=0;i<n;i++)
                {
                    if(a[i]<mid)up+=mid-a[i];
                    else if(a[i]>mid) down+=(a[i]-mid)>>1; 
                }
                if(up<=down)//降得情况要大于升的情况,因为降我可以+1,-2,让后-2,+1,这样两个数就都减一,然而升的话只能+1+1的升 
                {
                    l=mid+1;
                    ans=max(ans,mid);
                }
                else r=mid-1;
            }
            printf("%lld
    ",ans);
        }
    }

    poj1064

    http://poj.org/problem?id=1064

    经典的割绳子问题

    n段绳子,我要m段,问能割的最长长度

    #include<iostream>
    #include<math.h>
    #include<stdio.h>
    #include<string.h>
    double a[10010];
    const double eps=0.00000001;
    int n,m;
    int judge(double x)
    {
        int ans=0;
        for(int i=0;i<n;i++)
        ans+=(int)(a[i]/x);
        if(ans>=m) return 1;
        else return 0;
    } 
    
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i=0;i<n;i++) scanf("%lf",&a[i]);
            double l=0,r=100001;
            double t=0;
            while(r-l>=eps)
            {
                double mid=(l+r)/2;
                if(judge(mid))l=mid;
                else r=mid;
            }
            printf("%.2lf
    ",floor(r*100)/100);
        }
    }

    hdu3746

    给一个字符串,看缺几个可以构成循环

    kmp算法循环节裸题,先上模板

    void getnext()
    {
        int i=0,j=-1;
        next[0]=-1;
        while(i<tlen)
        {
            if(j==-1||t[i]==t[j])
            next[++i]=++j;
            else
            j=next[j];
        }
        
     } 
     int kmp_index()//统计出现位置
     {
         int i=0,j=0;
         getnext();
         while(i<slen && j<tlen)
         {
             if(j==-1 ||s[i]==t[j])//匹配成功则往下找 
             i++;j++;
             else //否则把t字符串往前移动 
             j=next[j];
         }
         if(j==tlen) return i-tlen;
         else return -1;
     }
     int kmp_count()//统计出现次数
     {
         int ans=0,i=0,j=0;
         while(i<slen)
         {
             if(j==-1||s[i]==t[j])//同上 
             i++,j++;
             else
             j=next[j];
             
             if(j==tlen)//判断是否有了 
             {
                 ans++;
                 j=next[j];
             }
         }
         return ans; 
     }

    代码

    #include<iostream>
    #include<string.h>
    using namespace std;
    int nextt[1000005];
    char a[100002];
    void getnext()
    {
        int i=0,j=-1;
        nextt[0]=-1;
        int t=strlen(a);
        while(i<t)
        {
            if(j==-1 || a[i]==a[j])
            nextt[++i]=++j;
            else j=nextt[j];
        }
    }
    int main()
    {
        int n;
        
        scanf("%d",&n);
        while(n--)
        {
            
            scanf("%s",a);
            getnext();
            int t=strlen(a);
            if(t%(t-nextt[t])==0&&nextt[t]!=0) printf("0
    ");
            else
            printf("%d
    ",(t-nextt[t])-t%(t-nextt[t]));//该字符串长度减去next[末尾]为循环节长度 
        }
        
    }

    codeforces

    http://codeforces.com/contest/1008/problem/D

    给一个长方体,判断是否可以刚好由几个相同的小长方体填满

    题解https://blog.csdn.net/weixin_42165981/article/details/81212814

    https://blog.csdn.net/codeswarrior/article/details/81146331

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5+10;
    ll C(int n,int m){//求组合数 
        ll ans = 1;
        for(int i = 1; i <= m; i++){
            ans = ans * (n-i+1) / i;
        }
        return ans;
    }
    bool check(int a,int b,int c){//如果111 
        if((a & 1) && (b & 2) && (c & 4))
            return true;
        if((a & 1) && (c & 2) && (b & 4))
            return true;
        if((b & 1) && (a & 2) && (c & 4))
            return true;
        if((b & 1) && (c & 2) && (a & 4))
            return true;
        if((c & 1) && (a & 2) && (b & 4))
            return true;
        if((c & 1) && (b & 2) && (a & 4))
            return true;
        return false;
    }
    int gcd(int a,int b){
        if(b == 0)
            return a;
        return gcd(b,a%b);
    }
    int cnt[10],use[10];
    int fac[maxn];
    int main(){
        //????????????
        for(int i = 1; i < maxn; i++){//通过打表来记录每个数的因子个数 
            for(int j = i; j < maxn; j += i){
                fac[j]++;
            }
        }
        int t,x,y,z;
        ll ans;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d%d",&x,&y,&z);
            int xy = gcd(x,y);
            int yz = gcd(y,z);
            int xz = gcd(x,z);
            int xyz = gcd(xy,z);
            //容斥原理 
            cnt[7] = fac[xyz];//111
            cnt[6] = fac[yz] - fac[xyz];//110
            cnt[5] = fac[xz] - fac[xyz];//101
            cnt[4] = fac[z] - fac[xz] - fac[yz] + fac[xyz];//100
            cnt[3] = fac[xy] - fac[xyz];//011
            cnt[2] = fac[y] - fac[xy] - fac[yz] + fac[xyz];//010
            cnt[1] = fac[x] - fac[xy] - fac[xz] + fac[xyz];//001
            ans = 0;
            for(int a = 1; a < 8; a++){
                for(int b = a; b < 8; b++){
                    for(int c = b; c < 8; c++){
                        if(check(a,b,c)){
                            memset(use,0,sizeof(use));
                            use[a]++;
                            use[b]++;
                            use[c]++;//???????????????
                            ll tmp = 1;
                            for(int i = 1; i < 8; i++){// 
                                if(use[i])
                                    tmp *= C(cnt[i]+use[i]-1,use[i]);
                            }
                            if(tmp > 0)
                                ans += tmp;
                        }
                    }
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }

    http://codeforces.com/contest/1008/problem/C

    题意给n个数,移动位置后算出最大的数(移动后的数字比以前大的个数)

    #include<bits/stdc++.h>
    using namespace std;
    int a[100002],b[100002];
    int main()
    {
        int n;
        cin>>n;
        for(int i=0;i<n;i++) 
        cin>>a[i];
        sort(a,a+n);
        int k=0;
        int ans=0;
        for(int i=0;i<n;i++)
        {
            while(k<=n&&a[k]<=a[i])//找出第一个比第i个数大的
            k++;
            if(k<=n) ans++,k++;
        }
        cout<<ans<<endl;
        
        return 0;
    }

    http://codeforces.com/contest/1008/problem/B

    题意:给了n个矩形的长和宽,可以翻转每一个矩形,也就是交换长和宽,让矩形的长或者宽形成非递增排列。

    #include<bits/stdc++.h>
    using namespace std;
    long long a[100002],b[100002],ans[100002];
    int main()
    {
        int n;
        cin>>n;
        for(int i=0;i<n;i++)
        cin>>a[i]>>b[i];
        
        ans[0]=max(a[0],b[0]);
        int k=1;
        for(int i=1;i<n;i++)
        {
            int t1=max(a[i],b[i]);
            int t2=min(a[i],b[i]);
            if(ans[i-1]>=t1) ans[i]=t1;
            else if(ans[i-1]>=t2) ans[i]=t2;
            else if(ans[i-1]<t2){
                //cout<<i<<" "<<
                cout<<"NO"<<endl;
                return 0;
            }
        }
        cout<<"YES"<<endl;
        return 0;
    }

    http://codeforces.com/contest/1011/problem/B

    题目大意:n个人m个食物,每个食物都有种类,每个人只能吃一种食物(无论哪一种),求最多能活多少天。

    #include<bits/stdc++.h>
    using namespace std;
    int a[105],b[105];
    int main()
    {
        int m,n;
        cin>>m>>n;
        memset(b,0,sizeof(b));
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
            b[a[i]]++;
        }
        //for(int i=0;i<10;i++) cout<<b[i]<<endl;
        if(m>n)
        cout<<"0"<<endl;
        else
        {
            int ans=1;
            for(int i=2;i<=100;i++)
            {
                int t=0;
                for(int j=1;j<=100;j++)
                {
                    t+=b[j]/i;
                    //cout<<t<<" ";
                    if(t>=m){
                        ans=max(ans,i);
                        break;
                    }
                }
                
            }
            cout<<ans<<endl;
        }
        return 0;
    }

    http://codeforces.com/contest/1011/problem/C

    给你飞机初始重量,飞机要在所有机场起飞降落。一开始会携带一定重量的汽油,然后每次飞的过程会消耗掉相应汽油,而每个机场给的值是1吨汽油能让他飞多少。

    #include<bits/stdc++.h>
    using namespace std;
    int n,m;
    int a[1005],b[1005];
    const long long eps=0.0000001;
    double jisuan(double x)
    {
        x-=(m+x)/a[0];
        for(int i=1;i<n;i++)
        {
            if(x<0) return -1;
            x-=(m+x)/b[i];
            if(x<0) return -1;
            x-=(m+x)/a[i];
        }
        if(x<0) return -1;
        x-=(m+x)/b[0];
        if(x<0) return -1;
        else if (x>0) return 1;
        else return 0;
    }
    int main()
    {
    
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
            if(a[i]==1)
            {
                cout<<-1<<endl;
                exit(0);
            }
        }
        for(int i=0;i<n;i++)
        {
            cin>>b[i];
            if(b[i]==1)
            {
                cout<<-1<<endl;
                exit(0);
            }
        }
        double l=1,r=1000000000;
        double t=0;
        while(r-l>=eps)
        {
            t++;
            if(t==62)
            {
                printf("%.7lf",(l+r)/2);
                return 0;
            }
            double m=(l+r)/2;
            if(jisuan(m)<0) l=m;
            else if(jisuan(m)>0) r=m;
        }
        printf("%.7lf",(l+r)/2);
    }

    今天突然有些新的想法,想要说些什么却不知道从何说起,有一种莫名的兴奋和激动,或许是觉得要想改变自己。

    我觉得以后没事写点东西还是挺好的,记录下自己的思想的转变,还有,要学会独立思考,这我觉得很重要

  • 相关阅读:
    打造基于CentOS7的xfce最简工作环境
    Linux下C程序的编辑,编译和运行以及调试
    修正 XE6 TListView 上方 SearchBok 右边的清除钮显示
    TabControl 显示彩色的图示 (XE6 Firemonkey)
    TSwitch 中文简繁显示支持(XE6 Android)
    改变 TMemo 的背景颜色 (Firemonkey)
    修正 XE5 Android 键盘三个问题
    Delphi 收藏
    展示 Popup 的使用方法
    ListView 下拉更新 (支持 Android)
  • 原文地址:https://www.cnblogs.com/wpbing/p/9483155.html
Copyright © 2011-2022 走看看