暴力求解法 算法竞赛入门经典2读书笔记 (附POJ 1321)

简单枚举

  讲一下自己的理解,所谓的枚举,一般不能纯暴力枚举的,应该先经过算法的优化,可以利用公式、题目的套路、已知算法进行优化,从而解决问题,目的是在规定的时间内完成。好像算法本来就是对各种暴力的优化,学习算法就是不断的优化优化。想起来C语言老师说过的,“不断地回过头来看自己的代码,用现有知识进行改进,你会发现,收获的远比想象得多”,赞。

725 - Division

仅仅枚举01234到98765,然后用数组代表0~9每一位是否存在。

代码见:725

11059 - Maximum Product

我们只需要两个循环,每次累乘,然后判断一下,用一个变量存储最大值,就能求出最大值。

 for(int i = 0; i < n; i++) 
    {
      long long p = 1;
      for(int j = i; j < n; j++) 
      {
        p *= a[j];
        if(p > ans) ans = p;
      }
    }


10976 - Fractions Again?!

1/k = 1/x + 1/y       =》         x = ky/(y-k)(先将x用y和k表示,简化计算)

x>=y>k

=》1/x<=1/y

=》1/x = 1/k -1/y  <=1/y

=》1/k<=2/y    =》  y<=k*2
然后我们只需要枚举y  (k,k*2】即可

for(int y = k+1; y <= k*2; y++)
    if(k*y%(y-k) == 0)


POJ 1321

看的别人的思路,其实这个还是比较好的,和刘汝佳书上思路差不多(可能所以回溯的都差不多吧),过段时间自己尝试看看能不能写出来更精简易懂的。

代码:

#include<iostream>//POJ 1321 八皇后问题
#include<cstdio>
#include<cstring>
using namespace std;
int s[10][10],vis[10];//棋盘,标记行数
int sum,n,k;
void dfs(int row,int cur)//按行搜索
{
    if(cur==k)//摆放的棋子数
    {
        sum++;
        return;
    }
    
    if(row>=n)//越过棋盘范围,就out
        return;
        
    for(int j=0;j<n;j++)//搜索这一行的每一列的那个数
    {
        if(s[row][j]&&!vis[j])//如果是可以放棋子的位置,并且还是空的
        {
            vis[j]=1;//既然尝试放了,先标明非空了
            dfs(row+1,cur+1);//继续下一行的搜索
            vis[j]=0;//如果这一行不满足,即没有放棋子,在标空
        }
    }
    dfs(row+1,cur);//可能现在已经将k个棋子放完,但我们还要继续搜索是否还有别的摆法
}
int main()
{
    char str;
    while(~scanf("%d%d",&n,&k))
    {
        if(n==-1&&k==-1)
            break;
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                cin>>str;
                if(str=='#')
                    s[i][j]=1;
                else
                    s[i][j]=0;
            }
        sum=0;
        dfs(0,0);//从第一行,从零开始计数
        printf("%d\n",sum);
    }
}


你可能感兴趣的:(算法,读书笔记,uva)