Five in a Row, Again-记录状态的dfs+剪枝

2023-10-16 20:38
文章标签 记录 状态 dfs row 剪枝 five

本文主要是介绍Five in a Row, Again-记录状态的dfs+剪枝,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

用一个二进制记录当前状态。

二进制中的0代表当前点已经被走过,1代表当前点还未走过。

如果当前二进制之前计算过,且值大于当前值的话,那么就终止不走。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int shuyu[5001];
int n;
int w[101][101];
int e[101][101];
int s[101];
int dp[5001];
void init()
{int ns=1;for(int i=1;i<=12;i++){shuyu[ns]=i;ns=ns*2;}for(int i=1;i<=5000;i++)if(shuyu[i]==0)shuyu[i]=shuyu[i-1];
}
void dos(int num,int exp,int as)
{//cout<<num<<" "<<exp<<" "<<as<<endl;if(num<dp[as])return ;dp[as]=num;if(as==0)return;int st;st=as;int ed;ed=as;while(ed){st=ed&(ed-1);st=ed-st;int pp=shuyu[st];if(exp>s[pp])dos(num+w[1][pp],exp+e[1][pp],as-(1<<(pp-1)));else dos(num,exp+e[1][pp],as-(1<<(pp-1)));ed=ed-st;}
}
int main()
{int _,i,j;init();scanf("%d",&_);while(_--){memset(dp,0,sizeof(dp));scanf("%d",&n);for(i=1;i<=n;i++){for(j=1;j<=n;j++){scanf("%d",&e[i][j]);}}for(i=1;i<=n;i++){for(j=1;j<=n;j++){scanf("%d",&w[i][j]);}}for(i=1;i<=n;i++){scanf("%d",&s[i]);}int as=0;int ns=1;for(i=1;i<=n;i++){as+=(1<<(i-1));}as-=1;int leap=1;int ans=0;while(leap){leap=0;for(i=2;i<=n;i++){if(s[1]<=s[i])continue;if((1<<(i-1))&as){s[1]+=e[1][i];as-=(1<<(i-1));ans+=w[1][i];leap=1;}}}if(as==0)cout<<ans<<endl;else{dp[as]=ans;dos(ans,s[1],as);cout<<dp[0]<<endl;}}
}


这篇关于Five in a Row, Again-记录状态的dfs+剪枝的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/220643

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

hdu1565(状态压缩)

本人第一道ac的状态压缩dp,这题的数据非常水,很容易过 题意:在n*n的矩阵中选数字使得不存在任意两个数字相邻,求最大值 解题思路: 一、因为在1<<20中有很多状态是无效的,所以第一步是选择有效状态,存到cnt[]数组中 二、dp[i][j]表示到第i行的状态cnt[j]所能得到的最大值,状态转移方程dp[i][j] = max(dp[i][j],dp[i-1][k]) ,其中k满足c

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

状态dp总结

zoj 3631  N 个数中选若干数和(只能选一次)<=M 的最大值 const int Max_N = 38 ;int a[1<<16] , b[1<<16] , x[Max_N] , e[Max_N] ;void GetNum(int g[] , int n , int s[] , int &m){ int i , j , t ;m = 0 ;for(i = 0 ;

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

hdu3006状态dp

给你n个集合。集合中均为数字且数字的范围在[1,m]内。m<=14。现在问用这些集合能组成多少个集合自己本身也算。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.Inp

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

实例:如何统计当前主机的连接状态和连接数

统计当前主机的连接状态和连接数 在 Linux 中,可使用 ss 命令来查看主机的网络连接状态。以下是统计当前主机连接状态和连接主机数量的具体操作。 1. 统计当前主机的连接状态 使用 ss 命令结合 grep、cut、sort 和 uniq 命令来统计当前主机的 TCP 连接状态。 ss -nta | grep -v '^State' | cut -d " " -f 1 | sort |