1. 程式人生 > >第十二屆北航程式設計競賽決賽網路同步賽: 浪哥的煩惱

第十二屆北航程式設計競賽決賽網路同步賽: 浪哥的煩惱

題目連結:https://biancheng.love/problem/587/index

題目描述

最近學校大檢查,要求上課認真聽講,這讓浪哥很是煩惱,因為這樣他就不能上課刷題了。但經過不懈的觀察,他發現領導檢查是有一定的規律的。不妨把每層樓的教室看成一排,從 1n 標號,領導每檢查完一個教室,就會從相鄰的一個或兩個教室中選擇一個繼續檢查,一個教室可能被檢查不止一次。

已知時刻 0 領導在 1 號教室,從 i 號教室走到 i+1 號教室需要 ti 時間,從 i+1 號教室走到 i 號教室也需要 ti 時間 (i=1,2,,n1),檢查一個教室的時間極短可忽略不計,放學時刻為 m

浪哥想要知道,放學之前(包括 m )的哪些時刻,領導是不可能檢查到他所在的 n 號教室的。

輸入

第一行包含一個正整數 T ,表示有 T 組測試資料。

接下來依次給出每組測試資料。對於每組測試資料:

第一行包含兩個正整數 nm

第二行包含 n1個正整數 t1,t2,,tn1

1T200,2n100,1m500,1tim

輸出

對於每組資料輸出一行,包含一些正整數,按升序給出,表示 n 號教室不可能被檢查的時刻。

對於本題,輸出中在一行的每個整數之間用恰好一個空格隔開,不能有其他額外空格。

輸入樣例

1
3 10
2 3

輸出樣例

1 2 3 4 6 7 8 10

樣例解釋

在放學前,領導有兩種不同的檢查方式會檢查到 3 號教室,分別是 1 -> 2 -> 3 1 -> 2 -> 1 -> 2 -> 3 ,其中到達 3 號教室的時刻分別為 5 9

這道題有兩種做法,第一種就是直接用母函式,三個for迴圈,這個for也不是全部迴圈,而且範圍較小,所以不會超時,程式碼如下:

//    >File Name: bianchenglove1.cpp
//    > Author: Webwei

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,vis[505];
int a[105];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		memset(vis,0,sizeof(vis));
		int s=0;
		for(int i=1;i<n;i++)
		{
			cin>>a[i];
			s+=a[i];
			a[i]*=2;
			if(s>m) break;
		}
		if(s<=m){
			vis[s]=1;
			for(int i=1;i<n;i++){
				for(int j=s;j<m;j++){
					for(int k=a[i];k+j<=m;k+=a[i])
					{
						if(!vis[k+j]) vis[k+j]=vis[j];
					}
				}
			}
		}
		int flag=0;
		for(int i=1;i<=m;i++)
		{
			if(!vis[i]){
				if(flag) cout<<" ";
				else flag=1;
				cout<<i;
			}
		}
		cout<<'\n';
	}
	return 0;
}

還有另一種就是dp,記憶化搜尋
#include<bits/stdc++.h>
using namespace std;
int tim[505];
int h=0;
int ans[505];
int n,m;
int us[105][505];
int dfs(int k,int t)
{

	if(k==n&&t<=m)  ans[t]=1;
	if(t>m||us[k][t])  return 0;
	if(k!=n)  dfs(k+1,t+tim[k]);
	if(k!=1)  dfs(k-1,t+tim[k-1]);
	us[k][t]=1;
}
int main()
{

	int t;
	cin >> t;
	while( t-- )
	{

		cin >> n >> m ;
		fill(ans , ans + m + 1 , 0);
		for(int i=1;i<n;i++)
		{
			cin>>tim[i];
		}
		memset(us,0,sizeof(us));
		dfs(1,0);
		int flag=0;
		for(int i=1;i<=m;i++){

			if(ans[i]==0){

				if(flag==0){

					cout<<i;
					flag=1;
				}else{

					cout<<" "<<i;
				}
			}
		}
		cout<<'\n';
	}
}