1. 程式人生 > 其它 >Hype新手入門教程:Hype使用者介面講解(上)

Hype新手入門教程:Hype使用者介面講解(上)

練習一下區間dp,總結一下題型

括號配對問題 Brackets Sequence


連結:https://172.16.79.125/contest/view.action?cid=831#problem/A

題意:給一串括號序列。依照合法括號的定義,加入若干括號,使得序列合法。

一道典題,思路是括號配對加上路徑回溯,找出輸入的所有不配對單括號,在輸出時將其補充成完整括號對即可

括號配對

求序列配對的括號量,使用三層迴圈,前兩層列舉長度和起點,然後要注意括號配對時更新dp值。由於合法的括號對都是巢狀或者並列的,所以第三層的列舉中間點只能幫我們解決括號的並列,但是不能解決括號的巢狀,所以我們還要自己加入判斷,即當該區間的左右端點括號匹配時,dp[l][r]=dp[l+1][r-1]+1

路徑回溯

這個也是典型,有兩種方法,一種是不開闢陣列,通過原來的dp轉移方程來遞迴,另一種是開一個數組(一般dp過程可以簡化陣列維度,但路徑回溯不可以,不過少部分題也可以),這個陣列用來記錄前驅(就是由誰更新了它),然後層層訪問前驅即可。
以前寫揹包的路徑回溯,兩種方法都比較簡單,現在看區間dp,感覺第二種好用點。區間dp由於第三層迴圈的存在,所以兩種方法都會麻煩一點,第一種得遍歷中間點,第二種得遞迴左區間和右區間。

程式碼:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int N = 1e2+10 , M = N<<1,mod=1e9+7;
typedef long long LL;
typedef pair<int,int> PII;
//#define x first 
//#define y second

//int h[N],e[M],ne[M],idx;
//
//void add(int a,int b)
//{
//	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
//}

struct Node
{
	int l1,r1;
	int l2,r2;
};

char s[N];

int f[N][N];

Node path[N][N];

int st[N];

void dfs(int l,int r)    //路徑回溯
{
	Node t =path[l][r];
	if(t.l1==l+1&&t.r1==r-1) 
	{
		st[l]=st[r]=1;
		dfs(l+1,r-1);
	}
	else if((t.l1|t.l2|t.r1|t.r2)==0) return;    //記得要加邊界條件
	else 
	{
		dfs(t.l1,t.r1);
		dfs(t.l2,t.r2);
	}
}

int check(int l,int r)    //檢查括號是否匹配
{
	if(s[l]=='('&&s[r]==')'||s[l]=='['&&s[r]==']') return 1;
	return 0;
}

void deal(char c)    //補全括號
{
	if(c=='('||c==')') cout<<"()";
	else if(c=='['||c==']') cout<<"[]";
}

void solve()        //區間dp
{
	cin>>s+1;
	int size=strlen(s+1);
	for(int len=2;len<=size;len++)
		for(int r=len;r<=size;r++)
		{
			int l=r-len+1;
			if(check(l,r))      //額外的判斷條件
			{
				Node& t =path[l][r];
				if(f[l][r]<f[l+1][r-1]+1) f[l][r]=f[l+1][r-1]+1,t.l1=l+1,t.r1=r-1;
			}
			
			for(int k=l;k<r;k++)
			{
				Node& t =path[l][r];
				int sum=f[l][k]+f[k+1][r];
				if(sum>f[l][r]) 
				{
					f[l][r]=sum;
					t.l1=l,t.r1=k;
					t.l2=k+1,t.r2=r;
				}
			}
		}
	
	dfs(1,size);
	
	for(int i=1;i<=size;i++)
	{
		if(!st[i]) deal(s[i]);
		else cout<<s[i];
	}
	cout<<'\n';
	
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
//	int T;
//	cin>>T;
//	while(T--) 
	solve();
}

鄉村郵局問題-Post Office(POJ-1160)