重走长征路---OI每周刷题记录---9月29日 2013 AC 20题

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

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

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

本周共计20题

测评地址:

bfs

1.细胞问题  //在线测评地址https://www.luogu.org/problemnew/show/P1451

2.Knight Moves  //在线测评地址https://vjudge.net/problem/POJ-1915

dfs

3.特殊的质数肋骨  //在线测评地址https://www.luogu.org/problemnew/show/P1218

高精度

阶乘统计

4.阶乘统计  //在线测评地址http://codevs.cn/problem/2156/

5.阶乘末尾的零  //在线测评地址http://codevs.cn/problem/2860/

6.阶乘问题  //在线测评地址https://www.luogu.org/problemnew/show/P1134

7.计算n!的值  //在线测评地址https://www.luogu.org/problemnew/show/P1009​​​​​​​

贪心

8.装箱问题  //在线测评地址https://www.luogu.org/problemnew/show/P1049

dp

数字三角形2-4

9.数字三角形2  //在线测评地址http://codevs.cn/problem/2189/

10.数字三角形3  //在线测评地址http://codevs.cn/problem/2193/

11.数字三角形4  //在线测评地址http://codevs.cn/problem/2198/

12.最长不下降子序列  //在线测评地址http://codevs.cn/problem/1576/

13.最小中间和  //在线测评网站http://codevs.cn/problem/1382/

14.导弹问题  //在线测评地址https://www.luogu.org/problemnew/show/P1020

15.均分纸牌  //在线测评地址https://www.luogu.org/problemnew/show/P1031

16.机器工厂  //在线测评地址https://www.luogu.org/problemnew/show/P1376

17.机器分配  //在线测评地址https://www.luogu.org/problemnew/show/P2066

dfs

18.素数环   //在线测评地址https://vjudge.net/problem/HDU-1016

模拟

19.黑色星期五  //在线测评地址https://www.luogu.org/problemnew/show/P1202

20.单数?双数?  //在线测评地址http://codevs.cn/problem/2163/

题解:

bfs

1.细胞问题

//P1451 求细胞数量
//在线测评地址https://www.luogu.org/problemnew/show/P1451
//每bfs一次,算一个细胞,同时把遇到的非0值置0
//算法的时间复杂度,若测试数据整个为1个细胞,100*100*(100)=10^6
//若测试数据整个为0个细胞,100*100=10^4
//样例通过,提交AC。2018-12-10
#include
#include
char s[110][110];
int next[][2]={{-1,0},{1,0},{0,-1},{0,1}};//上下左右
int vis[110][110],m,n;//突然想到vis[][]还可以有二维形式,开窍了。
struct Point{
    int x,y;
}q[12000],p;
void bfs(int x,int y){
    int h,t,nx,ny,i;
    h=t=1;
    q[t].x=x,q[t].y=y,vis[x][y]=1,s[x][y]='0',t++;
    while(h         p=q[h];
        for(i=0;i<4;i++){
            nx=p.x+next[i][0];
            ny=p.y+next[i][1];
            if(0<=nx&&nx                 s[nx][ny]='0',vis[nx][ny]=1;
                q[t].x=nx,q[t].y=ny,t++;
            }
        }
        h++;
    }
}
int main(){
    int i,j,cnt=0;
    memset(vis,0,sizeof(vis));
    scanf("%d%d",&m,&n);
    for(i=0;i         scanf("%s",s[i]);
    for(i=0;i         for(j=0;j             if(s[i][j]!='0'){
                cnt++;
                bfs(i,j);
            }
    printf("%d\n",cnt);
    return 0;
}

2.Knight Moves

//Knight Moves POJ - 1915 
//在线测评地址https://vjudge.net/problem/POJ-1915 
//借助 题图,样例,还是弄懂了该题。一个单词都没查 
//写代码的过程有些失误,但还是通过静态检查找到了问题。 
//q[t].s=s+1,t++;//此处写成 t++,q[t].s=s+1;
//样例通过,提交Runtime Error。
//仔细看了看,大意了, q[100000];//此处写成 q[10000]
//修改,提交AC。2018-12-10 20:23
#include
#include
int next[][2]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,-2},{2,-1},{2,1},{1,2}};
int vis[310][310],n;
struct Point{
    int r,c,s;
}q[100000];//此处写成 q[10000]
void bfs(int sr,int sc,int er,int ec){
    int h,t,r,c,s,i,nr,nc;
    h=t=1;
    q[t].r=sr,q[t].c=sc,q[t].s=0,t++,vis[sr][sc]=1;
    while(h         r=q[h].r,c=q[h].c,s=q[h].s;
        if(r==er&&c==ec){
            printf("%d\n",s);
            return;
        }
        for(i=0;i<8;i++){
            nr=r+next[i][0],nc=c+next[i][1];
            if(0<=nr&&nr                 vis[nr][nc]=1,q[t].r=nr,q[t].c=nc,q[t].s=s+1,t++;//此处写成 t++,q[t].s=s+1;
            }
        }
        h++;
    }
}
int main(){
    int t,sr,sc,er,ec;
    scanf("%d",&t);
    while(t--){
        memset(vis,0,sizeof(vis));
        scanf("%d",&n);
        scanf("%d%d%d%d",&sr,&sc,&er,&ec);
        bfs(sr,sc,er,ec);
    }
    return 0;
}


dfs

3.特殊的质数肋骨

//P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib
//在线测评地址https://www.luogu.org/problemnew/show/P1218
//一开始想用质数筛,但一看99999999,即10^9,O(n)明显超时
//还是用深搜。
//原以为会挺慢,测试下来,速度惊人。样例通过,提交AC。2018-12-12
//该题还有一个办法,打表。
#include
#include
int n,a[15];
int isPrime(int x){//质数 返回1,非质数返回 0
    int i;
    if(x==1)return 0;
    if(x==2)return 1;
    for(i=2;i*i<=x;i++)
        if(x%i==0)return 0;
    return 1;
}
void dfs(int step){
    int i,k,ans;
    if(step==n+1){
        ans=0;
        for(k=1;k<=n;k++)//此处写成 for(k=1;k<=n;i++) 真是昏到家了。
            ans*=10,ans+=a[k];
        if(isPrime(ans))printf("%d\n",ans);
        return ;
    }
    for(i=1;i<=9;i++){
        ans=0,a[step]=i;//此处写成a[k]=i//漏了此句a[k]=i
        for(k=1;k<=step;k++)
            ans*=10,ans+=a[k];
        if(isPrime(ans))
            dfs(step+1);
    }
}
int main(){
    scanf("%d",&n);
    dfs(1);
    return 0;
}

高精度

阶乘统计

4.阶乘统计

//2156 阶乘统计
//在线测评地址http://codevs.cn/problem/2156/
//long long 2^63=9223372036854775808
//           20!=2432902008176640000
//故,该题long long不会溢出
//对long long与int混搭,心存疑虑,立马测试,之后解惑。
//样例通过,提交AC。2018-12-10
#include
#define LL long long
int out[20];//输出的数
int main(){
    LL ans=1,b;
    int n,k,i,len;
    scanf("%d%d",&n,&k);
    for(i=1;i<=n;i++)
        ans*=i;
    while(ans%10==0)ans/=10;//去尾部的0
    len=0,b=ans;
    while(b){
        out[len++]=b%10;
        b/=10;
    }
    if(k>=len)printf("%lld",ans);
    else
        for(i=k-1;i>=0;i--)
            printf("%d",out[i]);
    return 0;
}

5.阶乘末尾的零

//2860 阶乘末尾的零
//在线测评地址http://codevs.cn/problem/2860/
//思路,统计每个数的因数10,5,2的个数
//每一对2,5对应一个结果0,每一个10对应一个结果0
//注意:1000!有249个零。
//考虑统计用long long
//担心10^8会超时,测试了一下,估计能险过
//提交AC.2018-12-10
#include
#include
#define LL long long
int min(LL a,LL b){
    return a }
int main(){
    LL cnt_2=0,cnt_5=0,cnt_10=0;
    int i,n,m;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        m=i;
        while(m%10==0)m/=10,cnt_10++;
        while(m%5==0)m/=5,cnt_5++;
        while(m%2==0)m/=2,cnt_2++;
    }
    printf("%lld\n",cnt_10+min(cnt_2,cnt_5));
    return 0;
}

6.阶乘问题

//P1134 阶乘问题
//在线测评地址https://www.luogu.org/problemnew/show/P1134
//思路,统计每个数的因数5,2的个数
//每一个10对应一个结果0若该数是10的整数倍,可直接跳过,不影响结果
//每一对2,5对应一个结果0,
//注意:注意:10,000,000!有2499999个零。
//考虑统计用long long
//担心5*10^7会超时,测试了一下,估计能险过
//提交AC.2018-12-10 对此次算法表示满意,全是自己编的。
#include
#define LL long long
int main(){
    LL cnt_2=0,cnt_5=0,i;
    int n,m,ans=1;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        m=i;
        if(m%10==0)m/=10;
        while(m%5==0)m/=5,cnt_5++;
        while(m%2==0)m/=2,cnt_2++;
        ans=(ans*m)%10;
    }
    if(cnt_2>cnt_5)
        for(i=1;i<=cnt_2-cnt_5;i++)
            ans=(ans*2)%10;
    else if(cnt_2         for(i=1;i<=cnt_5-cnt_2;i++)
            ans=(ans*5)%10;
    printf("%d\n",ans);
    return 0;
}

7.计算n!的值

//P1009 阶乘之和
//在线测评地址https://www.luogu.org/problemnew/show/P1009
//看完题目,就知道该用,高精度加法+高精度乘法 
//用高精度,总感觉挺糟糕的,代码量不小啊 
//该开多大的数组呢,先开大的吧,开到int z[2000] 
//之后,测试n=50,再将上述数组 缩小范围。 
//循环次数,外层循环(1+50)*50/2=1275,内部循环,大约没算一次大约1000,大致感觉不会超时 
//先编一个主体程序,再编高精度乘,只有才是高精度加 
//编的过程中,记得及时测试,否则,怎么错都不知道。 
//该题的优点是,高精度乘 发生在 数字*整数数组,编起来,相对简单些
//为了尽可能的避免,运算过程中int的溢出,准备对f[]采用long long
//突然想到n!=(n-1)!*n应该能省不少时间
//z[i]+=y[i]+x[i];//此处写成z[i]=y[i]+x[i];查了好久 花了30分钟。 
//测试了50的答案为31035053229546199656252032972759319953190362094566672920420940313
//maxn 开到 100即可
//测了一下,n=500反应也很快。决定将maxn开到1000
//样例通过,提交AC。2019-1-15 21:13
//翻看了之前,编写的代码,在伯仲之间,各有优缺点。
//详见https://blog.csdn.net/mrcrack/article/details/78473644
//1173 阶乘和 
#include
#include
#define maxn 1000
#define LL long long
LL f[maxn],ans[maxn],g[maxn];
void mul(int a,LL *f){
    int i;
    for(i=1;i<=f[0];i++)f[i]*=a;
    for(i=1;i<=f[0];i++){//进位处理
        f[i+1]+=f[i]/10;
        f[i]%=10; 
    }
    if(0     else if(f[i]>=10){
        while(f[i]>=10){
            f[i+1]+=f[i]/10;
            f[i]%=10;
            i++;
        }
        f[0]=i;
    }
}
void add(LL *x,LL *y,LL *z){
    int i;
    z[0]=y[0]>x[0]?y[0]:x[0];
    for(i=1;i<=z[0];i++){
        z[i]+=y[i]+x[i];//此处写成z[i]=y[i]+x[i];查了好久 
        z[i+1]+=z[i]/10;
        z[i]%=10;
    }
    if(z[i])z[0]=i;
}
int main(){
    int n,i;
    memset(ans,0,sizeof(0));
    scanf("%d",&n);
    memset(f,0,sizeof(f));
    f[0]=1,f[1]=1;
    for(i=1;i<=n;i++){
        mul(i,f);
        memset(g,0,sizeof(g));//漏了此句 
        add(f,ans,g);
        memcpy(ans,g,sizeof(g));
    }
    for(i=ans[0];i>=1;i--)printf("%lld",ans[i]);
    return 0;
}
 

贪心

8.装箱问题

//P1049 装箱问题
//NOIP 2001 普及组 
//在线测评地址https://www.luogu.org/problemnew/show/P1049 
//01背包问题,将物品的体积看成体积、价值即可。 
//样例通过,提交AC。2018-12-9 15:31 
#include
#include
int v[35],f[35][20100];
int max(int a,int b){
    return a>b?a:b;
}
int main(){
    int m,n,i,j;
    memset(f,0,sizeof(f));
    scanf("%d%d",&m,&n);
    for(i=1;i<=n;i++)
        scanf("%d",&v[i]);
    for(i=1;i<=n;i++)
        for(j=0;j<=m;j++)
            if(j                 f[i][j]=f[i-1][j];
            else
                f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+v[i]);
    printf("%d\n",m-f[n][m]);
    return 0;
}


dp

数字三角形2-4

9.数字三角形2

//2189 数字三角形W
//在线测评地址http://codevs.cn/problem/2189/ 
//没什么好办法,深搜dfs 
//担心的是,超时,试试看吧,没有办法的办法 
//该题,节点上最大值未告知,不过还是能应付的,a[i][j]%=100;//防止数据计算int溢出 100*25=2500
//样例通过,提交,测试点1,2WA。2019-1-14 20:24
//发现问题,dfs(a[1][1],1,1,1);//此处写成 dfs(0,1,1,1); 
//修改,提交AC。2019-1-14 20:35 
#include
#include
int n,a[30][30],b,c,sum,ans=0;
int max(int a,int b){
    return a>b?a:b;
}
void dfs(int sum,int step,int r,int c){//r行 c列 
    int i,j;
    if(step==n){
        ans=max(ans,sum%100);
        return ;
    }
    for(j=0;j<2;j++)
        dfs(sum+a[r+1][c+j],step+1,r+1,c+j);
}
int main(){
    int i,j;
    memset(a,0,sizeof(a));
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        for(j=1;j<=i;j++){
            scanf("%d",&a[i][j]);
            a[i][j]%=100;//防止数据计算int溢出 100*25=2500 
        }
    dfs(a[1][1],1,1,1);//此处写成 dfs(0,1,1,1);
    printf("%d\n",ans);
}

10.数字三角形3

//2193 数字三角形WW
//在线测评地址http://codevs.cn/problem/2193/
//一度想放弃,想看懂 数字三角形2 递推的解答,
//试图用在 该题上,无奈,一时难以看懂,只好回到深搜dfs的老路上。
//在想,在乱搜中,如何过指定的点,遇到非指定点就跳过去,
//一个想法突然冒出来,这不就是剪枝吗,太高兴了,算法有了。2019-1-15 06:08
//该题有个缺点,没说节点的最大值,在考虑int是否溢出
//样例通过,提交AC。2019-1-15 剪枝有些感觉了
#include
#include
#define maxn 30
int n,a[maxn][maxn],ans=-999999999;
int max(int a,int b){
    return a>b?a:b;
}
void dfs(int step,int sum,int r,int c){
    int j;
    if(r==n/2&&c!=n/2)//剪枝
        return;
    if(step==n){
        ans=max(ans,sum);
        return ;
    }
    for(j=0;j<2;j++)
        dfs(step+1,sum+a[r+1][c+j],r+1,c+j);
}
int main(){
    int i,j;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        for(j=1;j<=i;j++)
            scanf("%d",&a[i][j]);//此处写成scanf("%d",&a[i]);,昏招
    dfs(1,a[1][1],1,1);
    printf("%d\n",ans);
    return 0;
}

11.数字三角形4

//2198 数字三角形WWW
//在线测评地址http://codevs.cn/problem/2198/
//有了 剪枝 这个 技能,该题也就有信心了。
//该题的问题是,节点的最大值是多少,没说,存在int可能溢出的情况。
//样例通过,提交AC。2019-1-15 08:39
#include
#include
#define maxn 30
int n,a[maxn][maxn],x,y,ans=-999999999;
int max(int a,int b){
    return a>b?a:b;
}
void dfs(int sum,int step,int r,int c){
    int j;
    if(r==x&&c!=y)return;//剪枝
    if(step==n){
        ans=max(ans,sum);
        return ;
    }
    for(j=0;j<2;j++)
        dfs(sum+a[r+1][c+j],step+1,r+1,c+j);
}
int main(){
    int i,j;
    memset(a,0,sizeof(a));
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        for(j=1;j<=i;j++)
            scanf("%d",&a[i][j]);
    scanf("%d%d",&x,&y);
    dfs(a[1][1],1,1,1);
    printf("%d\n",ans);
    return 0;
}

12.最长不下降子序列

//最长不下降子序列 此题不好找,无奈找下题替换
//1576 最长严格上升子序列
//在线测评地址http://codevs.cn/problem/1576/
//样例通过,提交AC。2018-12-19
#include
#define maxn 5100
int a[maxn],d[maxn];
int max(int a,int b){
    return a>b?a:b;
}
int main(){
    int n,i,j,len=-1;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(i=1;i<=n;i++){
        d[i]=1;
        for(j=1;j             if(a[j]d[i])
                d[i]=d[j]+1,len=max(len,d[i]);
    }
    printf("%d\n",len);
    return 0;
}

13.最小中间和

//最小中间和 找不到 在线测评,只好找 基本类似 来替换
//1382 沙子合并
//在线测评网站http://codevs.cn/problem/1382/
//f[i][j] i->j之间的 最小和
//开一个前缀和b[i] 1->i的和
//f[i][i]=0;//此处真是,神来之笔
//最小的中间和的动归,完全是独立想出,高兴。
//样例通过,提交AC。2018-12-21
#include
#include
#define maxn 310
int a[maxn],f[maxn][maxn],b[maxn];
int min(int a,int b){
    return a }
int main(){
    int i,j,n,k;
    scanf("%d",&n);
    memset(f,127,sizeof(f)),b[0]=0;
    for(i=1;i<=n;i++){
        scanf("%d",&a[i]);
        f[i][i]=0;//此处真是,神来之笔
        b[i]+=b[i-1]+a[i];
    }
    if(n==1){//特判,省得添堵
        printf("%d\n",a[n]);
        return 0;
    }
    for(k=1;k<=n-1;k++)
        for(i=1;i<=n;i++)
            if(i+k<=n)
                for(j=i;j<=i+k;j++)
                    f[i][i+k]=min(f[i][i+k],f[i][j]+f[j+1][i+k]+b[i+k]-b[i-1]);
    printf("%d\n",f[1][n]);
    return 0;
}

14.导弹问题

//P1020 导弹拦截

//NOIP 普及组 1999
//在线测评地址https://www.luogu.org/problemnew/show/P1020 
//开数组d[]存储递减序列 
//二分法,找当前数据放置d[]数组中位置。
//样例通过,提交AC。2018-12-14 22:07
//算法时间复杂度,O(nlogn). 
#include
int a[100100],d[100100];
int main(){
    int i,k=1,ans1=0,left,right,mid,ans2=0;
    while(scanf("%d",&a[k])!=EOF)k++;
    d[0]=60000;
    for(i=1;i         if(d[ans1]>=a[i])
            ans1++,d[ans1]=a[i];//d[]是递减序列 
        else{
            left=0,right=ans1;
            while(left+1                 mid=(left+right)/2;
                if(d[mid]>=a[i])left=mid;//此处写成 if(d[ans1]>=a[i])left=mid;
                else right=mid;
            }
            d[right]=a[i];//目标,让该递减序列,每个位置的值都尽可能大 
        }
    printf("%d\n",ans1);
    d[0]=-1;
    for(i=1;i         if(d[ans2]             ans2++,d[ans2]=a[i];
        else{
            left=0,right=ans2;
            while(left+1                 mid=(left+right)/2;
                if(d[mid]                 else right=mid;
            }
            d[right]=a[i];//想清数据存储格式,采用left还是right,自然明白 
        } 
    printf("%d\n",ans2);
    return 0;
}

//P1020 导弹拦截
//NOIP 普及组 1999
//在线测评地址https://www.luogu.org/problemnew/show/P1020
//最长不上升子序列   导弹个数
//最长上升降子序列   拦截系统套数
//样例通过,提交WA,只通过了测试点1.
//修改if(a[j]d[i])//计算拦截系统,此处写成 if(a[j]<=a[i]&&d[j]+1>d[i])。
//提交,测试点1-10 AC,O(n^2)通过。2018-12-12 17:30
#include
#include
int a[100100],d[100100];
int max(int a,int b){
    return a>b?a:b;
}
int main(){
    int k=0,i,j,ans1=-1,ans2=-1;
    while(scanf("%d",&a[k])!=EOF)k++;
    for(i=0;i         d[i]=1;
        for(j=0;j             if(a[j]>=a[i]&&d[j]+1>d[i])
                d[i]=d[j]+1,ans1=max(ans1,d[i]);
    }
    for(i=0;i         d[i]=1;
        for(j=0;j             if(a[j]d[i])//计算拦截系统,此处写成 if(a[j]<=a[i]&&d[j]+1>d[i])
                d[i]=d[j]+1,ans2=max(ans2,d[i]);
    }
    printf("%d\n%d\n",ans1,ans2);
    return 0;
}

 

15.均分纸牌

//P1031 均分纸牌
//NOIP 2002 提高组
//在线测评地址https://www.luogu.org/problemnew/show/P1031
//纯模拟,由左往右开始填坑。
//很是高兴,一次提交,就AC。没有参考任何其它。2018-12-19
//样例过程如下
9  8  17 6
10 7  17 6
10 10 14 6
10 10 10 10

#include
#define maxn 110
int a[maxn];
int main(){
    int n,i,avg=0,cnt=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]),avg+=a[i];
    avg/=n;
    for(i=1;i         if(a[i]!=avg)
            a[i+1]+=a[i]-avg,cnt++;//a[i]多移走,少补进
    printf("%d\n",cnt);
    return 0;
}

16.机器工厂

//P1376 机器工厂
//在线测评地址https://www.luogu.org/problemnew/show/P1376
//吐糟该题,看了半天没看懂,出题人的第一要务,要让人看懂题
//若无能力表述清楚,至少,应将给出的样例解释清楚。
//对样例进行解释

4 5         共4周 每周每台保管费5
88 200   第1周  每台费用88  需200台
89 400   第2周  每台费用89  需400台
97 300   第3周  每台费用97  需300台
91 500   第3周  每台费用91  需500台

该样例数据计算

第1周 每台费用 88                       需200   花销88*200

第2周 每台费用 93   89                需400   花销89*400

第3周 每台费用 98   94  97          需300   花销94*300

第4周 每台费用 103 99  102 91   需300   花销91*300

                                                              总花销126900

//有了基本算法,在一堆价格中,取最小值,进行计算
//采用O(n)的算法
//总花销,最大值5000*10000=5*10^7 int不会溢出
//样例通过,提交90分,测试点6 WA.
//翻看题解,表示,不服,怎么会用到long long
//反复读题,才发现,每周最多10000台,每台最多花费5000,最多10000周
//那么最大值10000*5000*10000=5*10^11,现在同意用long long了
//long long cost=0;//之前写成 int cost=0;交90分,测试点6 WA.
//修改,提交AC。2019-1-16
//大意失荆州,题目还是要多读,最好还是要动纸笔。
#include
#include
#define maxn 10100
int n,s,a,b;//b该周的费用,a该周之前一周的费用
int min(int a,int b){
    return a }
int main(){
    int i,y;
    long long cost=0;//之前写成 int cost=0;交90分,测试点6 WA.
    a=999999999;
    scanf("%d%d",&n,&s);
    for(i=1;i<=n;i++){
        scanf("%d%d",&b,&y);
        a=min(a+s,b);
        cost+=a*y;
    }
    printf("%lld\n",cost);
    return 0;
}

17.机器分配

//P2066 机器分配
//在线测评地址https://www.luogu.org/problemnew/show/P2066
//在线测评地址http://ybt.ssoier.cn:8088/problem_show.php?pid=1266
//在两个在线测评网址之间切换,总算弄懂了题意。
//解释样例:
//公司1选3台 盈利50
//公司2选3台 盈利50
//公司3选3台 盈利30
//公司1选1台 盈利30 公司2选1台 盈利20 公司3选1台 盈利20 总共盈利 70
//f[i][j] i台机器 被 j个公司选 的最大盈利值
//打印 分公司编号和该分公司获得设备台数。没什么感觉
//那么,将动归的中间过程打印,找规律。
//发现
//f[1][1]=30,f[0][0]=0 i=1 j=1 k=1
//f[2][2]=50,f[1][1]=30 i=2 j=2 k=1
//f[3][3]=70,f[2][2]=50 i=3 j=3 k=1
//找到规律,以递归的方式打印结果。
//样例通过,提交10分,测试点2-10WA。2019-1-15 17:07
//有多组解的情况处理,if(f[i][j]<=f[i-1][j-k]+a[i][k]){//此处写成 if(f[i][j] //提交20分,测试点3-10WA。2019-1-15 17:10
//翻看了之前的代码https://blog.csdn.net/mrcrack/article/details/78440134
//发现for(k=0;k<=j;k++)//此处写成for(k=1;k<=j;k++)
//就这一处差别,造成了 20分 与 100分 的差距。2019-1-15 17:16
//觉的又困惑,针对样例,将for(k=0;k<=j;k++)的数据打印如下

f[1][1]=30 f[1][2]=40 f[1][3]=50
f[2][1]=30 f[2][2]=50 f[2][3]=60
f[3][1]=30 f[3][2]=50 f[3][3]=70

//将for(k=1;k<=j;k++)的数据打印如下

f[1][1]=30 f[1][2]=40 f[1][3]=50
f[2][1]=20 f[2][2]=50 f[2][3]=60
f[3][1]=20 f[3][2]=40 f[3][3]=70

//各位看到差别了吗.2019-1-15 17:20

//该题编写,还是比较满意的,除了一处k=0还是k=1是翻看之前的编写记录,其它都是独立编写,且独立改正的。2019-1-15 17:29
#include
#include
int a[15][20],f[15][20],g[15][20];
void print(int x,int y){//选择了x个公司,选择了y件机器
    if(x==0)return;
    print(x-1,y-g[x][y]);
    printf("%d %d\n",x,g[x][y]);
}
int main(){
    int n,m,i,j,k;
    memset(f,0,sizeof(f));
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            for(k=0;k<=j;k++)//此处写成for(k=1;k<=j;k++)//这是最关键的一行代码
                if(f[i][j]<=f[i-1][j-k]+a[i][k]){//此处写成 if(f[i][j]                     f[i][j]=f[i-1][j-k]+a[i][k];
                    g[i][j]=k;//选择了x个公司,选择了y件机器 ,此次需加入的机器数量k
                }
    printf("%d\n",f[n][m]);
    print(n,m);
    return 0;
}

dfs

18.素数环

//Prime Ring Problem HDU - 1016
//在线测评地址https://vjudge.net/problem/HDU-1016
//回溯+深搜
//要点,头尾两数和为质数
//提交Wrong Answer,发现 k++,printf("\nCase %d:\n",k);//此处写成 k++,printf("\nCase k:\n");
//提交Wrong Answer,估计 格式的 问题,继续修改
//觉得格式修改无误了,提交,竟然出现Presentation Error
//好歹知道现在出现的问题,就是格式问题。
//再读题,发现这么一句Print a blank line after each case.
//继续修改,提交AC。2018-12-12 一度想要求助网络,不过,还是忍住了,独立AC。
//ACM的提交方式,对格式要求真高。
#include
#include
int vis[30],a[30],n,kase=0;
int isPrime(int x){//质数 返回1 非质数 返回0
    int i;
    if(x==1)return 0;
    if(x==2)return 1;
    for(i=2;i*i<=x;i++)
        if(x%i==0)return 0;
    return 1;
}
void dfs(int step){
    int i,k;
    if(step==n+1){
        if(n>=2&&isPrime(a[1]+a[n])){//此处写成 if(isPrime(a[1]+a[n])
            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&&isPrime(a[step-1]+i)){
            vis[i]=1,a[step]=i;
            dfs(step+1);
            vis[i]=0;
        }
}
int main(){
    while(scanf("%d",&n)!=EOF){
        memset(vis,0,sizeof(vis));
        kase++;
        printf("Case %d:\n",kase);//此处写成 k++,printf("\nCase k:\n");
        a[1]=1,vis[1]=1;
        dfs(2);
        printf("\n");//少了此句
    }
    return 0;
}

模拟

19.黑色星期五

//P1202 [USACO1.1]黑色星期五Friday the Thirteenth
//在线测评地址https://www.luogu.org/problemnew/show/P1202 
//看了看该题,有点烦,编好该题,对日期的处理应是手到擒来。 
//闰年判定函数, 
//月天数数组。
//编完一个函数,或功能,测试是必需的。 
//思路,算出每个月13号,从1900年开始的天数,再进行星期几的计算。
//样例通过,提交AC。2018-12-9 17:00 
#include
#include
int month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};//month[1]表示1月的天数 
int week[10];
int run(int year){//闰年返回1,平年返回0
    if(year%100==0)return year%400?0:1;//整百年        
    else return year%4?0:1;//非整百年
}
int main(){
    int n,i,j,year,tot=0,day=0;//tot当年开始之前的总天数。 day=0当年开始的总天数 
    memset(week,0,sizeof(week));//week[1]周一,week[6]周六,week[0]周日 
    scanf("%d",&n);
    for(i=0;i         year=1900+i;
        month[2]=run(year)?29:28;
        if(i>0)tot+=(365+run(year-1));
        day=tot+13;
        for(j=0;j<12;j++){
            day+=month[j];
            week[day%7]++;
        }
    }
    printf("%d %d",week[6],week[0]);
    for(i=1;i<=5;i++)
        printf(" %d",week[i]);
    return 0;

20.单数?双数?

//2163 单数??双数????
//在线测评地址http://codevs.cn/problem/2163/
//该题,数据(1 <= I <= 10^60)看起来挺吓人 
//起始用字符串存储,判断最后一位是否奇偶即可
//样例通过,提交AC。2018-12-9 21:18
#include
#include
char s[100];
int main(){
    int t,len;
    scanf("%d",&t);
    while(t--){
        scanf("%s",s);
        len=strlen(s);
        if((s[len-1]-'0')%2)printf("odd\n");
        else printf("even\n");
    }
    return 0;

2019-1-16 AC 该周内容

你可能感兴趣的:(跟着大佬学算法)