西工大算法实验2020年复习

算法实验

DFS

堡垒问题

#include <iostream>
using namespace std;
int n;
int a[4][4];

int mcnt;//Max
int cnt;//now

void dfs(int m);
bool ok(int i,int j);

int main(){
    cin>>n;
    while (n){
        char c;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                cin>>c;
                if(c=='X')a[i][j]=1;
                else a[i][j]=0;
            }
        }
        mcnt=cnt=0;
        dfs(0);
        cout<<mcnt<<endl;
        cin>>n;
    }
    return 0;
}

void dfs(int m){
    if(m==(n*n)){
        if(mcnt<cnt){mcnt=cnt;}
    }else{
        int i=m/n;
        int j=m%n;
        if(ok(i,j)){
            a[i][j]=-1;
            cnt++;
            dfs(m+1);
            cnt--;
            a[i][j]=0;
        }
        //看清楚两个dfs的位置
        dfs(m+1);
    }
}

bool ok(int i,int j){
    int x,y;
    if(a[i][j]==1) return false;
    for (int x = i-1,y=j; x >=0 ; x--) {
        if(a[x][y]==1)break;
        if(a[x][y]==-1)return false;
    }
    for (int x = i,y=j-1; y >=0 ; y--) {
        if(a[x][y]==1)break;
        if(a[x][y]==-1)return false;
    }
    return true;
}

农场灌溉 图像周长

农场灌溉

#include <iostream>

using namespace std;
int walk[4][2]{
    0,-1,
    1,0,
    0,1,
    -1,0//要逐一做匹配
};
int oppo[4]={
        2,3,0,1
};
int square[11][4]={
    //这个要按顺序写
    //左下右上
    1,0,0,1,
    0,0,1,1,
    1,1,0,0,
    0,1,1,0,
    0,1,0,1,
    1,0,1,0,
    1,0,1,1,
    1,1,0,1,
    1,1,1,0,
    0,1,1,1,
    1,1,1,1
};
int m,n;

int cnt;

int farm[50][50];

int used[50][50];

int moveto(int x,int y,int d){
    int newx=x+walk[d][0];
    int newy=y+walk[d][1];

    if(newx<m&&newx>=0 && newy<n&&newy>=0){
        if(!used[newx][newy]){
            int num1=farm[x][y];
            int num2=farm[newx][newy];
            if(square[num1][d]==1 && square[num1][oppo[d]]==1){
                return newx*n+newy;
            }


        }
    }
    return -1;
}

void dfs(int k){
    int x=k/n;
    int y=k%n;
    used[x][y]=1;
    int next;
    for (int d = 0; d <4 ; ++d) {
        next=moveto(x,y,d);
        if(next>=0){
            dfs(next);
        }
    }
}
int main() {
    while (cin>>m>>n &&!(m==-1&&n==-1)){
        cin.get();
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < m; ++j) {
                farm[i][j]=cin.get()-'A';
                used[i][j]=0;
            }
        cin.get();//吃掉换行
        }
        for (int k = 0; k < m*n; ++k) {
            if(!used[k/n][k%n]){
                dfs(k);
                cnt++;
            }
        }
        cout<<cnt<<endl;
        //每次都把能通的都给used掉
        //然后再搜每一个方格就行了
    }

    return 0;
}
//这道题主要是数据结构的设计

图像周长的算法设计

可以向八个方向走

但 上下左右均正方向 越界、碰墙时才会length++

斜向只为走到那个格子里面 之后单独判断那个格子加不加length

注意是从0开始 还是从1开始

图的m着色问题

从第一个节点开始涂

循环canpaint(节点,颜色)

走到最后方案数+1

#include <iostream>
int n,r,m;
int side[20][20];
using namespace std;
int plan;
int color[10];

bool canpaint(int k, int c) //顶点k能否涂颜色c
{
    for(int i=0; i<k; i++)
    {
        if(side[k][i]==1&&c==color[i])  //相连的顶点有重复的颜色
        {
            return false;
        }
    }
    return true;
}
void dfs(int k)
{
    if(k==n)
    {
        plan++;
    }
    else
    {
        for (int c = 1; c <= m; ++c)
        {
            if(canpaint(k,c))
            {
                color[k]=c;
                dfs(k+1);
            }
        }
    }
}


int main() {
    cin>>n>>r>>m;
    for (int i = 0; i < r; ++i) {
        int u,v;
        cin>>u>>v;
        side[u][v]=side[v][u]=1;
    }
    dfs(0);
    printf("%d",plan);
    return 0;
}

必考题

LCS

#include <iostream>
#include<string>
using namespace std;
string a,b;
int la,lb;
int dp(int i,int j){
    if(i==-1 || j==-1){
        return 0;
    }
    if(a[i]==b[j]){
        return dp(i-1,j-1)+1;
    }
    else{
        int num1=dp(i-1,j);
        int num2=dp(i,j-1);
        if(num1>num2)return num1;
        return num2;
    }

}
int main()
{
    cin>>a>>b;
    la=a.length();
    lb=b.length();
    cout<<dp(la-1,lb-1)<<endl;
    return 0;
}

加1乘2平方

#include <iostream>
#include <queue>
using namespace std;
int m,n;
queue<int>q1;
int used[10000];
int step[10000];
void init(){
     for(int i=0; i<n; i++)  //初始化步数数组、判重数组
    {
        step[i]=used[i]=0;
    }

    while(!q1.empty()){
        q1.pop();
    }
    q1.push(m);
    used[m]=1;
}
int go(int m,int i){
switch(i){
    case 0:return m+1;
    case 1:return m*2;
    case 2:return m*m;
}
}

bool isTarget(int now, int next)    //判断next是否到达目标?
{
    if(next<=n&&!used[next])    //判越界&判重
    {
        used[next]=1;   //记录到达
        step[next]=step[now]+1; //记录步数

        if(next==n) //若到达目标数字,返回true
        {
            return true;
        }
        else        //未到达则入队
        {
            q1.push(next);
        }
    }
    return false;
}
int bfs(){
    int now,next;
while(!q1.empty()){
    now=q1.front();
    q1.pop();
    for(int ssd=0;ssd<=2;ssd++){
        next=go(now,ssd);
        if(next<=n && !used[next] ){
                //直接越界了
            used[next]=1;
            step[next]=step[now]+1;
        if(next==n){return step[next];}else{
            q1.push(next);
        }
        }
    }
}
return -1;
}
int main()
{
    cin>>m>>n;
    init();
    cout<<bfs()<<endl;
    return 0;
}

0-1Package DFS

#include <iostream>
#include<cstdio>
using namespace std;
int n,c;
int w[10];
int p[10];
int maxp;
int pnow;
int wnow;
void dfs(int m){
    if(m==n){
        if(maxp<pnow)maxp=pnow;
        return;
    }else{
        if(wnow+w[m]<=c){
            wnow+=w[m];
            pnow+=p[m];
            dfs(m+1);
            pnow-=p[m];
            wnow-=w[m];
        }
            dfs(m+1);
    }

}
int main()
{
    while(cin>>n>>c && (n!=0||c!=0)){
        int i;
     maxp=pnow=wnow=0;
    for(i=0;i<n;i++){
        scanf("%d",&w[i]);
    }
    for(i=0;i<n;i++){
        scanf("%d",&p[i]);
    }
    dfs(0);
    printf("%d\n",maxp);
    }
    return 0;
}
	

素数环

#include <iostream>
#include<cstdio>
#include<math.h>
using namespace std;
int tmp[21];
int used[21];
bool wait =true;
bool isprime(int m){
    if(m==1)return true;
    if(m==2)return true;
    if(m==3)return true;
    if(m==5)return true;
    if(m==7)return true;
for(int k=2;k<=sqrt(m);k++){
    if(m%k==0){
        return false;
    }
}
    return true;

}
void dfs(int m){
if(wait){
    if(m==21){
            if(wait){
            if(isprime(tmp[1]+tmp[20])){
            for(int i=1;i<=19;i++){
            printf("%d ",tmp[i]);
        }
        printf("%d",tmp[20]);
        printf("\n");
        wait=false;
        }
            }

        return;
    }else{
        for(int s=1;s<=20;s++){
            if(used[s]==0){
                if(m>=2){
                    if(isprime(tmp[m-1]+s)){
                        tmp[m]=s;
                        used[s]=1;
                        dfs(m+1);
                        used[s]=0;
                }
                }else{
                     tmp[m]=s;
                     used[s]=1;
                     dfs(m+1);
                     used[s]=0;
                }
            }

        }
    }

}
}
int main()
{
    dfs(1);
    return 0;
}

二分查找

注意使用循环防止堆栈溢出

while内再mid 切忌要不然进不了循环

学会单步调试

不然真的很难顶

#include <iostream>
#include<cstdio>
#include<math.h>
using namespace std;
int a[10000];
int n;
int m;
bool binarysearch(int a[],int st,int ed,int k){
    while(st<=ed){
        int mid=(st+ed)/2;
        if(a[mid]>k){
            ed=mid-1;
        }else if(a[mid]<k){
            st=mid+1;
        }else{
            return true;
        }
    }
    return false;
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    cin>>m;
    for(i=0; i<m; i++)
    {
        int k;
        cin>>k;
        if(binarysearch(a,0,n-1,k))
        {
            cout<<"Yes"<<endl;
        }
        else
        {
            cout<<"No"<<endl;
        }
    }
    return 0;
}

0-1Package DFS++

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=2050;
int n,c,w[maxn],p[maxn];
int dfs(int now,int res){
    if(now=n+1) return 0;
    int ans1=0,ans2=0;
    if(res>=w[now]){
        ans1=dfs(now+1,res-w[now])+p[now];
    }
    //装 然后进去一个
    //不装然后再给爷走一个
    ans2=dfs(now+1,res);
    //都回来之后比一比
    //后面的都已经装好了
    if(ans1>ans2) return ans1;
    return ans2;
}
int main() {
    int i,j;
    scanf("%d%d",&n,&c);
    for (int i = 0; i < n; ++i) {
        cin>>w[i],p[i]=w[i];
    }
    cout<<dfs(1,c)<<endl;
    return 0;
}

0-1Package DP

//I have got it!
#include<cstdio>
#include<iostream>
using namespace std;
#define maxn 2050
int n,c,w[maxn],v[maxn],dp[maxn];
int main(){
    //Don't Fear Everyone
    int i,j,maxnumber=0;
    cin>>n>>c;
    for(i=1;i<=n;i++){
        cin>>w[i];
        v[i]=w[i];
    }
    for(i=1;i<=n;i++){
        for(j=c;j>=1;j--){
            //printf("%d %d\n",i,j);
            if(j>=w[i] && dp[j-w[i]]+v[i]>dp[j]){
                dp[j]=dp[j-w[i]]+v[i];
            }
    }
    }


    for (i = 1; i <=c ; ++i) {
        if(maxnumber<dp[i]){
            maxnumber=dp[i];
        }
    }
    printf("%d\n",maxnumber);
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值