1. 程式人生 > >挖地雷(動態規劃 輸出路徑)

挖地雷(動態規劃 輸出路徑)

【例9.6】挖地雷


時間限制: 1000 ms         記憶體限制: 65536 KB
 

【題目描述】

在一個地圖上有n個地窖(n<=200),每個地窖中埋有一定數量的地雷。同時,給出地窖之間的連線路徑,並規定路徑都是單向的,且保證都是小序號地窖指向在序號地窖,也不存在可以從一個地窖出發經過若干地窖後又回到原來地窖的路徑。某人可以從任一處開始挖地雷,然後沿著指出的連線往下挖(僅能選擇一條路徑),當無連線時挖地雷工作結束。設計一個挖地雷的方案,使他能挖到最多的地雷。

【輸入】

第一行:地窖的個數;

第二行為依次每個地窖地雷的個數;

下面若干行:

xi yi   //表示從xi可到yi,xi<yi。

最後一行為"0 0"表示結束。

【輸出】

k1-k2-…-kv    //挖地雷的順序

挖到最多的雷。

【輸入樣例】

6
5 10 20 5 4 5
1 2
1 4
2 4
3 4
4 5
4 6
5 6
0 0

【輸出樣例】

3-4-5-6
34

【來源】


No


錯誤的程式碼:

/*
6
5 10 20 5 4 5
1 2
1 4
2 4
3 4
4 5
4 6
5 6
0 0
*/
#include<iostream>
#include<cstring>
#define MAXN 200
using namespace std;
bool a[MAXN][MAXN];//a[i][j]表示第i個地窖和第j個地窖是否是通路 
int w[MAXN];//每個地窖的地雷數 
int f[MAXN];//f[i]表示從第i個地窖開始挖的最多地雷數 
int suf[MAXN];
int main()
{
	memset(a,0,sizeof(a));
	memset(w,0,sizeof(w));
	memset(f,0,sizeof(f));
	long n,i,j,x,y,l,k,maxn;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>w[i];
	}
	while(cin>>x>>y)
	{
		if(x==0&&y==0) break;
		a[x][y]=true;
	}
	f[n]=w[n];//初始狀態
	for(i=n-1;i>=1;i--)
	{		 
		for(j=i+1;j<=n;j++)
		{
			if((a[i][j])&&f[i]<w[i]+f[j])
			{
				f[i]=w[i]+f[j];
				suf[i]=j;
			}
		}
	} 
	k=1;
	for(i=1;i<=n;i++)//從n個數中找最大值 
	{
		if(f[i]>f[k]) k=i;
	}
	maxn=f[k];
	cout<<k;//先輸出起始點 
	k=suf[k];
	while(k!=0)//向後的連結串列 
	{
		cout<<"-"<<k;
		k=suf[k];
	}
	cout<<endl;
	cout<<maxn<<endl;
	return 0;
} 


正確的程式碼:

/*
6
5 10 20 5 4 5
1 2
1 4
2 4
3 4
4 5
4 6
5 6
0 0
*/
#include<iostream>
#include<cstring>
#define MAXN 200
using namespace std;
bool a[MAXN][MAXN];//a[i][j]表示第i個地窖和第j個地窖是否是通路 
int w[MAXN];//每個地窖的地雷數 
int f[MAXN];//f[i]表示從第i個地窖開始挖的最多地雷數 
int suf[MAXN];
int main()
{
	memset(a,0,sizeof(a));
	memset(w,0,sizeof(w));
	memset(f,0,sizeof(f));
	long n,i,j,x,y,l,k,maxn;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>w[i];
	}
	while(cin>>x>>y)
	{
		if(x==0&&y==0) break;
		a[x][y]=true;
	}
	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]=w[i]+l;
		suf[i]=k;
	} 
	k=1;
	for(i=1;i<=n;i++)//從n個數中找最大值 
	{
		if(f[i]>f[k]) k=i;
	}
	maxn=f[k];
	cout<<k;//先輸出起始點 
	k=suf[k];
	while(k!=0)//向後的連結串列 
	{
		cout<<"-"<<k;
		k=suf[k];
	}
	cout<<endl;
	cout<<maxn<<endl;
	return 0;
}