8.7 洛谷1-3暴力枚举+div3

算法1-3--暴力枚举

统计方形(数据加强版)

枚举边长--对于此边长横排能分几个,纵列能分几个相乘 
正方形:(n-i+1)*(m-i+1) 
长方形:(n-i+1)*(m-j+1)  if(i==j)continue; 两边长不相等!唯一区别正方形和长方形

烤鸡

枚举每个配料的克数! 十个循环!

三连击(升级版)

看是否存在三个数满足某个比例--该三个数有最小公因数--1至1000/最大倍数! 除以最大份数!
则枚举,判断对应三个数是都满足题目要求(数组存个数判断每个数出现次数是否为1,最后输出还是对应比例乘积输出即可!)

[NOIP2002 普及组] 选数

dfs选择! 
dfs(int x,int sum,int cnt)  //从哪开始  总和多少  选几个数了 符合条件之后一定要return!
void dfs(int x, int sum, int num) {
    if (num == k) if (isprime(sum)) {
        cnt++; return;
    }
    for (int i = x + 1; i <= n; i++) {
        dfs(i, sum + a[i], num + 1);
    }
}
for (int i = 1; i <= n; i++) 
        dfs(i, a[i],1);

组合的输出

dfs:1.数的个数 起始位置 和 等
     2.注意满足条件return回溯! 中间的a[]数组赋值输出不会对外层的dfs数组的值造成影响!
     3.对于全排列类似问题记得恢复现场!
dfs起始点 枚举每一个点为第一个数用数组存不会发生乱序现象! 等到下一个外层,a[k]的值又被覆盖了 每赋值完,会进行下一层的dfs  在下一层输出完成后 会返回至上一层!及搜索与回溯! 原来背负爱的值已经输出了!
所以回溯一定要返回return;
cout << setw(3) << x;  输出3个场宽的元素!

全排列问题

典型dfs!要记得恢复现场!

[NOIP2004 普及组] 火星人

从某个排列开始继续全排列m个输出:
学会第一遍排及排为你要开始排列的序列!
void dfs(int step){
    if(flagx==1) return;  //已经输出了!
    if(step>n){
        flag++;
        if(flag==m+1){
            输出 flagx=1;
        }
        return;
    }
    for(int i=1;i<=n;i++){
        if(flag==0) i=a[step];  👍👍
//还没开始 则从该排列开始! 直接更改赋值!
        if(!st[i]){
            st[i]=true;
            a[step]=i;
            dfs(step+1);
            st[i]=false;
        }
    }
}
dfs(1); 

涂国旗

直接前缀和求个数  枚举所需要的行数! i<n-1 j<n 即可!

First Step (ファーストステップ)

特殊情况要考虑!  ->注意考虑k==1情况   注意循环是k个!
可以直接用flag来判断不满足时,先为true 遇到不满足直接赋值false,为true输出!

[NOIP2008 提高组] 火柴棒等式

枚举每个数所需火柴数  注意会有2|3位数相加情况!
枚举从0-1000和0-1000不会有3 3和3 3重复情况!
求位数:先拷贝再求!
特殊情况0+多位+细节

妖梦拼木棒

求组合数:(f[i]*(f[i]-1)) >>1
求有没有一个组合使两数之和为另一个数:if (b[j] && b[i - j])
是否重复判断j==i-j就行! 不等再来组合数!!!

kkksc03考前临时抱佛脚

    //对于这种分支的,可以直接dfs枚举!
    l += a[k][i];//左边!
    dfs(k + 1, i);
    l -= a[k][i];//对于第一个数而言是原先这两步的原因!
    r += a[k][i];//右边!
    dfs(k + 1, i);
    r -= a[k][i];//因为下一次又要重新分配3,所以要剪掉! 对于第一个数而言最后回溯到这里因为没有下一个数了,所以剪不剪都不影响了

[COCI2008-2009#2] PERKET

dfs每种材料选与不选:每次dfs都判断min(abs)
相当于求所有组合起来的数!
所有i开一遍头,每次选不一样!right! 所以相当于爆搜!
void dfs(int r,int st, int ss, int kk) {
    ans = min(ans, abs(ss - kk));
    if (st > n) {
        cout << endl;
        return;
    }
    //1
    //1+2 1+3 1+4  因为是会枚举来选择的 所以是这种结果!
    //1+2+3 1+2+4 
    for (int i = st + 1; i <= n; i++) {
        dfs(r + 1, i, ss * s[i], kk + k[i]);
    }
}
//主函数中再从第一个数开始dfs 每次开头不一样!
for(int i=1;i<=n;i++)  dfs(2,i, s[i], k[i]);

div3(8.7)

AArray Coloring

奇数个奇数相加为奇数  则如果奇数个数为奇数,永远也不会两块同奇偶

BMaximum Rounding

因为要求四舍五入后最大的值,则从左往右遍历找到第一个会进位的pos(>=5||==4&&下一个>=5)
其实可以reverse这样就不用处理第0位了直接判断即可!
如果不存在pos直接输出a,如果pos=0直接输出1+00000 否则处理先改到当前位置,再循环判断是否会有4 5情况!(这一步最重要!)

CAssembly via Minimums

重点:从小到大遍历a数组,对于ai则有len-i-1个比它大的数,那么在b数组中就有len-i-1个数字ai,则从小到大遍历b数组,每次x+=len-i-1即找到下一个数,输出在循环判断。len-0-1 len-1-1即每次减1,使用--cnt x+=cnt计数! 对于最后一个数(循环条件cnt!=0)没有考虑比它大的,最大不会超过1额,则最后再输出一个1e9! 
//输出他的个数=在a数组中比他大的个数,等于也相当于大!
//输出小的则该数一定在原数组中! 所以在求原数组时才会输出这个数!

你要抽象出的是性质!根据数据的性质或者是答案的相对性质来解题!要加油啊!还有很多题目要刷!学习时间要保证!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值