算法实验
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;
}