重走长征路---OI每周刷题记录---10月12日 2013

总目录详见https://blog.csdn.net/mrcrack/article/details/84471041

做题原则,找不到测评地址的题不做。2018-11-28

重走长征路---OI每周刷题记录---10月12日  2013

测评地址:

模拟

美元   //在线测评地址http://codevs.cn/problem/2209/

dp

乘积最大   //在线测评地址https://www.luogu.org/problemnew/show/P1018

                 http://codevs.cn/problem/1017/

传球游戏   //在线测评地址https://www.luogu.org/problemnew/show/P1057

摆花   //在线测评地址https://www.luogu.org/problemnew/show/P1077 

背包dp

公路乘车   //在线测评地址http://codevs.cn/problem/2154/ 

找啊找啊找gf   //在线测评地址https://www.luogu.org/problemnew/show/P1509

dfs

n皇后   //在线测评地址http://codevs.cn/problem/2194/

题解:

模拟

美元

//2209 美元=doller=刀=knife
//在线测评地址http://codevs.cn/problem/2209/ 
//题意没说明,应该是该天,可买也可不买,回头看看,只是通过样例做了说明 
//该题核心是,找到买点(峰),根据买点找卖点(谷)
//对最后一个买点进行特判,看是买还是不买
//该题思维量挺大 
//极端数据1000买进,1卖出,共计50次操作100*10^50=10^52 int肯定溢出,long long 也溢出
//不过,不准备采用高精度算法,采用long long 多拿些分数
//看了输出结果,多虑了,采用double即可。 
//样例通过,提交,测试点4,5,7,8,9,10WA,得分40
//以下为40分代码。2018-12-30 19:27 
//基本确认,是上述算法的问题,没有数据,很难找到算法问题
//找到新的在线测评地址https://www.luogu.org/problemnew/show/P1968
//提交,发现测试点4,5,7-10WA。 
//发现之前做过,但与今日思路完全不同,看看题解里是否有数据,或与今日思路相近算法
//翻看此文代码https://blog.csdn.net/wx2306/article/details/79213196恍然大悟
//是自己想得太简单,还是想得太复杂了?
//该题的算法比较符合人性,有得赚就走。无论你是怎么想的,这就是最赚钱的办法
//是故不积跬步,无以致千里;不积小流,无以成江海。
//样例通过,提交AC。2018-12-30 20:18 
//以下为AC代码。 
#include <stdio.h>
int a[110];
double ans=100; 
int main(){
    int n,i;
    scanf("%d",&n); 
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    for(i=1;i<n;i++)
        if(a[i]>a[i+1])
            ans=ans*a[i]/a[i+1];
    printf("%.2lf\n",ans); 
    return 0;
}

//2209 美元=doller=刀=knife
//在线测评地址http://codevs.cn/problem/2209/ 
//题意没说明,应该是该天,可买也可不买,回头看看,只是通过样例做了说明 
//该题核心是,找到买点(峰),根据买点找卖点(谷)
//对最后一个买点进行特判,看是买还是不买
//该题思维量挺大 
//极端数据1000买进,1卖出,共计50次操作100*10^50=10^52 int肯定溢出,long long 也溢出
//不过,不准备采用高精度算法,采用long long 多拿些分数
//看了输出结果,多虑了,采用double即可。 
//样例通过,提交,测试点4,5,7,8,9,10WA,得分40
//以下为40分代码。2018-12-30 19:27 
//基本确认,是上述算法的问题,没有数据,很难找到算法问题
//找到新的在线测评地址https://www.luogu.org/problemnew/show/P1968
//提交,发现测试点4,5,7-10WA。 
//发现之前做过,但与今日思路完全不同,看看题解里是否有数据,或与今日思路相近算法
//翻看此文代码https://blog.csdn.net/wx2306/article/details/79213196恍然大悟
//是自己想得太简单,还是想得太复杂了?
//该题的算法比较符合人性,有得赚就走。无论你是怎么想的,这就是最赚钱的办法
//是故不积跬步,无以致千里;不积小流,无以成江海。
//样例通过,提交AC。2018-12-30 20:18 
//以下为AC代码。 
//翻看了之前的代码,发现写得挺妙,但决不是自己想出来的。动态规划 
//思路如下,同一天兑换成美元或马克,都对应最大值
//样例通过,提交AC。2018-12-30 21:08 
#include <stdio.h>
double dp1=100,dp2=0;//dp1 最大美元值,dp2 最大马克值 均发生在当日 
double max(double a,double b){
    return a>b?a:b;
}
int main(){
    int n,i,a;
    scanf("%d",&n); 
    for(i=1;i<=n;i++){
        scanf("%d",&a);
        dp1=max(dp1,dp2*100/a);
        dp2=max(dp2,dp1*a/100); 
    }
    printf("%.2lf\n",dp1); 
    return 0;
}

//2209 美元=doller=刀=knife
//在线测评地址http://codevs.cn/problem/2209/ 
//题意没说明,应该是该天,可买也可不买,回头看看,只是通过样例做了说明 
//该题核心是,找到买点(峰),根据买点找卖点(谷)
//对最后一个买点进行特判,看是买还是不买
//该题思维量挺大 
//极端数据1000买进,1卖出,共计50次操作100*10^50=10^52 int肯定溢出,long long 也溢出
//不过,不准备采用高精度算法,采用long long 多拿些分数
//看了输出结果,多虑了,采用double即可。 
//样例通过,提交,测试点4,5,7,8,9,10WA,得分40
//以下为40分代码。2018-12-30 19:27 
#include <stdio.h>
int a[110],b[110];//b[i]买点
double ans=100; 
int main(){
    int n,i,j;
    scanf("%d",&n);
    a[0]=a[n+1]=0;//为了找出峰值而设计 
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    b[0]=0;
    for(i=1;i<=n;i++)
        if(a[i-1]<a[i]&&a[i]>=a[i+1])
            b[++b[0]]=i;//存储峰值位置
    for(i=1;i<b[0];i++) 
        for(j=b[i]+1;j<=b[i+1]-1;j++)//找谷,卖点
            if(a[j-1]>=a[j]&&a[j]<a[j+1]){
                ans=ans*a[i]/a[j];
                break;
            }
    //最后一个买点进行特判,买还是不买
    a[n+1]=1100;//为了找出最后的 谷 而设计,因1≤A≤1000 
    for(j=b[0]+1;j<=n;j++)
        if(a[j-1]>=a[j]&&a[j]<a[j+1]){
            ans=ans*a[b[b[0]]]/a[j];//此处写成 ans=ans*a[b[0]]/a[j];
            break;
        }
    printf("%.2lf\n",ans); 
    return 0;
}
dp

乘积最大

//P1018 乘积最大
//NOIP 2000 提高组 
//在线测评地址https://www.luogu.org/problemnew/show/P1018 
//没什么太好的办法,决定采用深搜dfs 
//算法的时间复杂度40^6=4*10^9拿部份分吧 
//考虑了一下,结果采用long long
//样例通过,提交,测试点7-10WA,60分,深搜差不多到头了。
//以下为60分代码。2018-12-31 13:44 

//不用高精度,若想AC,可在此处提交http://codevs.cn/problem/1017/
#include <stdio.h>
#include <string.h>
#define LL long long
int N,K;
char s[50];
int a[50],b[50];
LL ans=-1;
LL max(LL a,LL b){
    return a>b?a:b;
}
LL value(int start,int end){
    int i;
    LL c=0;
    for(i=start;i<=end;i++){
        c*=10;
        c+=a[i];
    }
    return c;
}
void dfs(int step){
    int i,j;
    LL d=1;
    if(step==K+1){
        for(j=1;j<=K;j++)
            d*=value(b[j-1]+1,b[j]);//此处写成 d*=value(b[j-1],b[j]);
        d*=value(b[K]+1,N);//最后一个数字特判 
        ans=max(ans,d);
        return;
    }
    for(i=b[step-1]+1;i<=N;i++){
        b[step]=i;
        dfs(step+1);
    }
}
int main(){
    int i;
    scanf("%d%d%s",&N,&K,s+1);
    for(i=1;i<=N;i++)a[i]=s[i]-'0';
    b[0]=0;
    dfs(1);
    printf("%lld\n",ans);
    return 0;
}

传球游戏

//P1057 传球游戏
//NOIP 2008 普及组 
//在线测评地址https://www.luogu.org/problemnew/show/P1057 
//递推公式容易想到f[i][j]=f[i-1][j-1]+f[i-1][j+1] 
//难点在于 如何赋初值 边界处理 循环是先n还是m 
//以上难点由 模拟 样例 来解决
//在考虑f[][]采用int还是long long
//还是测试一下,比较稳妥,
//测试了 30 30
//输出155117522 
//放心了,提交AC。2019-1-1 08:13 
#include <stdio.h>
#include <string.h>
int f[35][35];
int main(){
    int n,m,i,j,a,b;
    memset(f,0,sizeof(f)),f[0][1]=1;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)
        for(j=1;j<=n;j++){
            a=j-1,b=j+1;
            if(a==0)a=n;
            if(b==n+1)b=1;
            f[i][j]=f[i-1][a]+f[i-1][b];
        }
    printf("%d\n",f[m][1]);
    return 0;

 

摆花

//P1077 摆花
//NOIP 2012 普及组 
//在线测评地址https://www.luogu.org/problemnew/show/P1077 

//方案数
//样例通过,提交AC。2018-12-31 22:19 
#include <stdio.h>
#include <string.h>
#define mod 1000007
int f[110][110],a[110];
int main(){
    int n,m,i,j,k;
    memset(f,0,sizeof(f));
    f[0][0]=1;//此句很关键 
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    for(i=1;i<=n;i++)
        for(j=0;j<=m;j++)
            for(k=0;k<=a[i];k++)
                if(j>=k)f[i][j]=(f[i][j]+f[i-1][j-k])%mod;
    printf("%d\n",f[n][m]);
    return 0;
}
背包dp

公路乘车

//2154 公路乘车
//在线测评地址http://codevs.cn/problem/2154/ 
//完全背包问题,可转化为多重背包问题 
//难度在于求 最小费用 
//样例通过,提交AC。2019-1-1 19:37 
#include <stdio.h>
#include <string.h>
int w[15],c[15],s[15],f[15][110];
int min(int a,int b){
    return a<b?a:b;
}
int main(){
    int n=10,m,i,j,k;
    memset(f,127,sizeof(f)),f[0][0]=0;//此处写成 memset(f,127,sizeof(127)),f[0][0]=0; 昏招 
    for(i=1;i<=n;i++)
        scanf("%d",&c[i]),w[i]=i;
    scanf("%d",&m);
    for(i=1;i<=n;i++)
        s[i]=m/w[i];//转化为多重背包
    for(i=1;i<=n;i++)
        for(j=0;j<=m;j++)//此处写成 for(j=1;j<=m;j++)
            for(k=0;k<=s[i];k++)
                if(j>=k*w[i])
                    f[i][j]=min(f[i][j],f[i-1][j-k*w[i]]+k*c[i]);//此处写成 f[i][j]=min(f[i][j],f[i-1][j-k*w[i]]+c[i]); 也是昏招 
    printf("%d\n",f[n][m]);
    return 0;
}
 

找啊找啊找gf

//P1509 找啊找啊找GF
//在线测评地址https://www.luogu.org/problemnew/show/P1509
//https://www.luogu.org/problemnew/solution/P1509此文不仅原理讲得好,代码也写得棒

//P1509 找啊找啊找GF
//在线测评地址https://www.luogu.org/problemnew/show/P1509
//开两个动归数组dpNum[][][]数量,dpTime[][][]时间 [n][rmb][rp]
//“保证MM数量的情况下花费的最少总时间”此句对解题十分关键
//数量是第一,在保证数量的情况下,处理总时间
//01背包
//此文https://blog.csdn.net/legan/article/details/8888101三维数组写得好,就是本人要找的,学习了。
//样例通过,提交AC。2019-1-2
#include <stdio.h>
#include <string.h>
int dpNum[105][105][105],dpTime[105][105][105];
int rmb[105],rp[105],time[105];
int min(int a,int b){
    return a<b?a:b;
}
int main(){
    int i,j,k,n,m,r;
    memset(dpNum,0,sizeof(dpNum)),memset(dpTime,0,sizeof(dpTime));
    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d%d%d",&rmb[i],&rp[i],&time[i]);
    scanf("%d%d",&m,&r);
    for(i=1;i<=n;i++)
        for(j=0;j<=m;j++)
            for(k=0;k<=r;k++){
                dpNum[i][j][k]=dpNum[i-1][j][k];//写错位置,写到if之内//此句关键
                dpTime[i][j][k]=dpTime[i-1][j][k];//写错位置,写到if之内//此句关键
                if(j>=rmb[i]&&k>=rp[i]){//同时满足
                    if(dpNum[i][j][k]<dpNum[i-1][j-rmb[i]][k-rp[i]]+1){
                        dpNum[i][j][k]=dpNum[i-1][j-rmb[i]][k-rp[i]]+1;
                        dpTime[i][j][k]=dpTime[i-1][j-rmb[i]][k-rp[i]]+time[i];
                    }else if(dpNum[i][j][k]==dpNum[i-1][j-rmb[i]][k-rp[i]]+1)//此处写成else if(dpNum[i][j][k]=dpNum[i-1][j-rmb[i]][k-rp[i]]+1) 昏招//保证MM数量的情况下花费的最少总时间
                        dpTime[i][j][k]=min(dpTime[i][j][k],dpTime[i-1][j-rmb[i]][k-rp[i]]+time[i]);
                }
            }
    printf("%d\n",dpTime[n][m][r]);
    return 0;
}


dfs

n皇后 

//2194 N皇后
//在线测评地址http://codevs.cn/problem/2194/
//算法:深搜+回溯
//测试了,感觉12或13有超时嫌疑
//样例通过,提交,竟然AC,好吧,那么就不优化了。2019-1-2
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int a[20],cnt=0,n,vis[20];//a[i]=j,i代表行,j代表列;cnt代表解的总数
void dfs(int step){
    int i,j,k,flag;
    if(step==n+1){
        cnt++;
        if(cnt<=3){
            printf("%d",a[1]);
            for(k=2;k<=n;k++)printf(" %d",a[k]);
            printf("\n");
        }
        return;
    }
    for(i=1;i<=n;i++)
        if(vis[i]==0){
            flag=0;
            for(j=1;j<=step-1;j++)
                if(abs(i-a[j])==abs(step-j)){//此处写成if(abs(a[i]-a[j])==abs(i-j))//对角线 判定
                    flag=1;
                    break;
                }
            if(flag==0){
                vis[i]=1;
                a[step]=i;
                dfs(step+1);
                vis[i]=0;//回溯
            }
        }
}
int main(){
    memset(vis,0,sizeof(vis));
    scanf("%d",&n);
    dfs(1);
    printf("%d\n",cnt);
    return 0;
}

终于AC了一周的内容,甚是高兴,一个好的开始。2019-1-2

猜你喜欢

转载自blog.csdn.net/mrcrack/article/details/85345119
今日推荐