您的位置:首页 > 其它

ural 1152 搜索或状压

2016-05-23 22:36 309 查看
n个阳台,每个阳台上有怪物,第一个阳台跟最后一个相邻,每次攻击其中一个阳台,那么相邻的两个也会被破坏掉,但是你攻击一次,剩下的没有被消灭的怪兽就会攻击你,问消灭所有怪兽 所受伤害值最少是多少

#include <bits/stdc++.h>
#include<cmath>
#include<cstdlib>
#define INF 0x3f3f3f3f
using namespace std;
int ans;
int n;
int a[25];
int sum=0;
int vis[1000];
int Mi=INF;
void DFS(int sum,int mi)
{
if(mi>=Mi)      ///剪枝
return ;
if(sum==0)
{
Mi=min(Mi,mi);
return;
}
for(int i=0; i<n; i++)
{
if(!vis[i])
{
int t1=(i+n-1)%n;
int t2=(i+1)%n;
vis[i]=1;
if(!vis[t1]&&!vis[t2])
{
vis[t1]=vis[t2]=1;
sum=sum-a[t1]-a[t2]-a[i];
mi+=sum;
DFS(sum,mi);
vis[t1]=vis[t2]=0;
mi-=sum;
sum=sum+a[t1]+a[t2]+a[i];
}
else if(!vis[t1])
{
sum=sum-a[t1]-a[i];
mi+=sum;
vis[t1]=1;
DFS(sum,mi);
vis[t1]=0;
mi-=sum;
sum=sum+a[t1]+a[i];
}
else if(!vis[t2])
{
sum=sum-a[t2]-a[i];
mi+=sum;
vis[t2]=1;
DFS(sum,mi);
vis[t2]=0;
mi-=sum;
sum=sum+a[t2]+a[i];
}
else    ///忘记自己本身也要相加了
{
sum=sum-a[i];
mi+=sum;
DFS(sum,mi);
mi-=sum;
sum=sum+a[i];
}
vis[i]=0;
}
}

}
int main()
{

while(~scanf("%d",&n))
{
Mi=INF;
memset(vis,0,sizeof(vis));
sum=0;
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
DFS(sum,0);
printf("%d\n",Mi);
}

return 0;
}


记忆化搜索写法

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;
int a[25], f[(1<<21)+10];
bool vis[(1<<21)+10];
int n;
int dfs(int x, int s)
{
if (vis[x]) return f[x];
vis[x]=true;
if (x==0) return f[x]=0;
int res=2100000000;
for (int i=1; i<=n; i++)
{
int newx=x, news=s;
for (int j=i-1; j<=i+1; j++)
{
int k=j;
if (j==0) k=n; else if (j==n+1) k=1;
if (newx&(1<<(k-1)))
{
news-=a[k];
newx-=(1<<(k-1));
}
}
if (newx!=x)
res=min(res, dfs(newx, news)+news);
}
return f[x]=res;
}

int main()
{
int s=0;
scanf("%d", &n);
for (int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
s+=a[i];
}
memset(f, 63, sizeof(f));
memset(vis, 0, sizeof(vis));
f[(1<<n)-1]=0;
printf("%d", dfs((1<<n)-1, s));
}//hzj
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: