https://www.luogu.org/problem/show?pid=1220
原本想用搜索先超时一把
然后发现剪枝居然过了
首先 对于每个位置,去寻找左边没关掉的灯或者右边没有关掉的灯。
之后造深搜 ,寻找最优情况。
然后 在搜索中我们发现,如果此时的和大于记录中的和的话,
那么这个搜索是没有必要继续走下去的,所以就结束掉这个叶子。
就像动态规划只保留最大值一样。
搜索的好处是,不仅能知道最大值,而且可以输出其路径。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
int d[10005];//记录灯的功率
int lef,righ,minx;
int run(int x,int y)//记录跑到了哪个位置
{
while(d[x]==0&&x>=lef&&x<=righ)
x+=y;
return x;
}
void dfs(int l,int s,int sum,int n)
{
//cout<<l<<' '<<s<<' '<<sum<<' '<<n<<endl;
//cout<<run(l,1)<<' '<<run(l,-1)<<' '<<righ<<' '<<lef<<endl<<endl;
if(s>minx) return;//如果现有和大于记录值 结束叶子。
if(n==1)
{
if(s<minx)
minx=s;
return ;
}
int t=d[l];
sum-=t;
d[l]=0;
int x;
if(run(l,1)<=righ)//往右跑
{
x=run(l,1);
dfs(x,s+sum*(x-l),sum,n-1);
}
if(run(l,-1)>=lef)//往左跑
{
x=run(l,-1);
dfs(x,s+sum*(l-x),sum,n-1);
}
d[l]=t;//回溯
}
int main()
{
int n,m;
cin>>n>>m;
int x,y;
int sum=0;
righ=0;
lef=100000000;
minx=1000000000;
int t,l;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
if(x<lef) lef=x;
if(x>righ) righ=x;
d[x]=y;
sum+=y;
if(i==m)
{
d[x]=0;
t=y;
l=x;
}
}
dfs(l,0,sum-t,n);
cout<<minx<<endl;
}
下面是输出路径
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
int d[10005];
int dp[10005];//动态记录路径变化
int c[10005];//记录最小值路径
int re;
map<int ,int > tag;
int lef,righ,minx;
int run(int x,int y)
{
while(d[x]==0&&x>=lef&&x<=righ)
x+=y;
return x;
}
void dfs(int l,int s,int sum,int n)
{
//cout<<l<<' '<<s<<' '<<sum<<' '<<n<<endl;
//cout<<run(l,1)<<' '<<run(l,-1)<<' '<<righ<<' '<<lef<<endl<<endl;
dp[n]=tag[l];
if(s>minx) return;
if(n==1)
{
if(s<minx)
{
for(int i=re;i>=1;i--)//更新最小值路径
{
c[i]=dp[i];
}
minx=s;
}
return ;
}
int t=d[l];
sum-=t;
d[l]=0;
int x;
if(run(l,1)<=righ)
{
x=run(l,1);
dfs(x,s+sum*(x-l),sum,n-1);
}
if(run(l,-1)>=lef)
{
x=run(l,-1);
dfs(x,s+sum*(l-x),sum,n-1);
}
d[l]=t;
}
int main()
{
int n,m;
cin>>n>>m;
re=n;
int x,y;
int sum=0;
righ=0;
lef=100000000;
minx=1000000000;
int t,l;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
tag[x]=i;
if(x<lef) lef=x;
if(x>righ) righ=x;
d[x]=y;
sum+=y;
if(i==m)
{
d[x]=0;
t=y;
l=x;
}
}
dfs(l,0,sum-t,n);
cout<<minx<<endl;
for(int i=n;i>=1;i--)//输出路径
{
cout<<c[i]<<' ';
}cout<<endl;
}