dp
一开始按照书上的方法用dp写
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
long f[201]={0},w[201],c[201]={0};
bool a[201][201]={0};
long i,j,n,x,y,l,k,maxx;
memset(f,0,sizeof(f));
memset(c,0,sizeof(c));
memset(a,false,sizeof(a));
cin>>n;
for(i=1;i<=n;i++)
cin>>w[i];
do
{
cin>>x>>y;
if((x!=0)&&(y!=0)) a[x][y]=true;
}while((x!=0)||(y!=0));
f[n]=w[n];
for(i=n-1;i>=1;i--)
{
l=0;k=0;
for(j=i+1;j<=n;j++)
if((a[i][j])&&(f[j]>l))
{
l=f[j];
k=j;
}
f[i]=l+w[i];
c[i]=k;
}
k=1;
for(j=2;j<=n;j++)
if(f[j]>f[k]) k=j;
maxx=f[k];
cout<<k;
k=c[k];
while(k!=0)
{
cout<<" "<<k;
k=c[k];
}
cout<<endl;
cout<<maxx<<endl;
}
三个tle一个wa
然后放弃dp了……(当然可以用dp……)
接下来才是重点
核心部分–链表遍历(其实只是比较像)
存三个参数a[i][1]来存储当前地窖有多少个地雷,a[i][2]来存储通过这个地窖最多可以挖到多少个地雷,a[i][3]来存储,如果要挖到最多的地雷,我们经过这个地窖之后要去哪个地窖。
跟p1020的最长不下降子序列有点像啊……
具体看代码吧(附带注释)
#include<bits/stdc++.h>
using namespace std;
int main()
{
bool f[210][210];//邻接矩阵
int a[210][4],n;//a数组
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i][1]);//读入地雷数量
a[i][2]=a[i][1];//默认最长和是自身
a[i][3]=0;//后继是0代表结束
}
for(int i=0;i<=209;i++)
for(int j=0;j<=209;j++)
f[i][j]=false;//邻接矩阵的初始化,默认都不能通
int x=0;
for(int i=1;i<=n-1;i++)
for(int j=i+1;j<=n;j++)
{
cin>>x;
if(x==1) f[i][j]=true;//在图中造路
}
for(int i=n-1;i>=1;i--)
{
int maxx=0,next=0;//maxx代表当前这个地窖过去以后可以挖掉多少地雷,next代表要挖到最多的地雷,接下来应该去哪里
for(int j=i+1;j<=n;j++)
if((a[j][2]>maxx)&&(f[i][j]))//如果能挖到的地雷多于当前记录的,并且ij之间通路
{
maxx=a[j][2];
next=j;//更新累加和与标记
}
if(next>0)//如果更改过
{
a[i][2]=a[next][2]+a[i][1];//那么就把累加和记录进去
a[i][3]=next;//更新当前结点的后继
}
}
int ans=0;
int first=0;
for(int i=1;i<=n;i++)
if(a[i][2]>ans)
{
ans=a[i][2];
first=i;
}//来寻找要挖到最多的地雷,第一个对哪个地窖下手。
while(first>0)//真的像链表遍历
{
printf("%d ",first);//打印路径
first=a[first][3];
}
printf("\n%d",ans);//把路径长度打印出来
return 0;
}
庆祝ac
(ppt就不弄了)