vijos1026-隱式圖搜尋(回溯|spfa)-毒藥?毒藥
阿新 • • 發佈:2018-12-24
https://vijos.org/p/1026
給定m個病和n個藥,每個藥對m個病有三種可能的情況,1可以治癒,-1當沒病時生病,0 無效。問至少多少藥,可以使病全部治好,如果不可以的話,就輸出”The patient will be dead.”
思路:講真我真的不知道這是隱式圖搜尋什麼鬼,不過一說最少,不是bfs就是動態規劃(dfs其實也能寫,不過一般都麻煩)wa了好幾發,因為對藥的規則不是特別瞭解。
自己列個表就能清楚 (這是上週寫的題,演草紙找不到了qwq)。 只有兩種情況可以轉移:
1 自己有病,但是這個藥可以治(是1)。
2 自己沒病,但是這個藥時-1
code one:回溯的思路,(感覺自己回溯什麼的都寫不利索了,還是太弱)
#include <bits/stdc++.h>
using namespace std;
/* 用一個map來存一下,然後暴力搜尋
*/
typedef long long ll;
const int maxn=200;
vector<int>q[maxn];
bool vis[maxn];
int m,n;
int ans;
const int mx=1<<11;
int mp[mx];
void dfs(ll sta,int num){
//cout<<" "<<num<<endl;
if(num>n)return ;
if(mp[sta]<=num)return;
mp[sta]=num;
if(sta==0){
ans=min(ans,num);
return;
}
for(int j=1;j<=n;j++){
if(vis[j])continue;
ll sta1=sta;
for(int i=0;i<q[j].size();i++){
if(q[j][i]==1&&((1 <<i)&sta1)){
sta1^=(1<<i);
}
else if(q[j][i]==-1&&!((sta&(1<<i)))){
sta1^=(1<<i);
}
}
vis[j]=true;
dfs(sta1,num+1);
vis[j]=false;
}
return;
}
int main()
{ int a;
scanf("%d%d",&m,&n);
ans=1e7;
memset(mp,0x3f,sizeof(mp));
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
scanf("%d",&a);
q[i].push_back(a);
}
}
ll s=(1<<m)-1;
dfs(s,0);
if(ans==1e7){
puts("The patient will be dead.");
}
else{
printf("%d\n",ans);
}
return 0;
}
code two: 用spfa
#include <bits/stdc++.h>
using namespace std;
/* 回溯的時候t了。
用一個map剪枝會好很多。
還有沒有弄清題意。
*/
typedef long long ll;
const int maxn=200;
vector<int>q[maxn];
const int mx=1<<11;
bool vis[mx];
int d[mx];
int m,n;
void spfa(ll s){
queue<ll>qu;
memset(d,0x3f,sizeof(d));
memset(vis,false,sizeof(vis));
d[s]=0;
vis[s]=true;
qu.push(s);
while(!qu.empty()){
ll u=qu.front();
qu.pop();
vis[u]=false;
if(!u){
printf("%d\n",d[0]);
break;
}
for(int i=1;i<=n;i++){
ll sta=u;
for(int j=0;j<m;j++){
if(q[i][j]==1&&((1ll<<j)&u)){
sta^=(1<<j);
}else if(q[i][j]==-1&&!((1ll<<j)&u)){
sta^=(1<<j);
}
}
if(d[sta]>d[u]+1){
d[sta]=d[u]+1;
if(!vis[sta]){
vis[sta]=true;
qu.push(sta);
}
}
}
}
if(d[0]==0x3f3f3f3f){
puts("The patient will be dead.");
}
else{
;
}
}
int main()
{ int a;
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
scanf("%d",&a);
q[i].push_back(a);
}
}
ll s=(1<<m)-1;
//dfs(s,0);
spfa(s);
return 0;
}