2021.1.3搜尋測試
【雜言】:
寡人怎麼也沒想到 T1寫掛了,
【\(T1\)】:
【題目描述】:
給出一個n個未知數的方程,\(x_1,x_2,x_3......x_n\)求\(x_1+x_2+x_3....+x_n==S\)的正整數解的個數,並且要保證,對於任意\(i (1<=i< n)\) \(x_i\)與\(x_{i+1}\)相差不大於\(p\)
【資料範圍】:
對於 \(30%\) 資料 \(2<=n<=10 ,p=0,S<=30;\)對於 \(100%\) 資料 \(2<=n<=10,p<=3 , S<=30;\)保證資料有梯度。
【考場程式碼】:(只有三十分,合著我暴力掛了):
/* by : Zmonarch 知識點 :搜尋 */ #include <cstdio> #include <algorithm> #include <cmath> #include <iostream> #include <queue> #include <set> #include <stack> #include <cstring> #define int long long using namespace std ; inline int read() { int x = 0 , f = 1 ; char ch = getchar() ; while(!isdigit(ch)) { if(ch == '-') f = - 1 ; ch = getchar() ; } while( isdigit(ch)) { x = x * 10 + ch - '0' ; ch = getchar() ; } return x * f ; } int n , tot , s , p ; void search(int now , int last ,int rest) { //printf("sum : %d\n" ,rest) ; if(now == n + 1 ) //現在已經加到了最後一個數 { if (rest == 0) tot ++ ;//方案數++ return ; } for(int i = 1 ; i < s && abs(i - last ) <= p; i++)//前一個數和後一個數不能超過p { search(now + 1 , i , rest - last - i) ; } } signed main() { // freopen("math.in" , "r" , stdin) ; // freopen("math.out" , "w" , stdout) ; n = read() , s = read() , p = read() ; //for(int i = 1 ; i <= s ; i++) if(p == 0) //因為是正整數, 所以如果相差為零, 那麼也就只有一種情況, 那就是全部都是同一個數的時候,除不盡就不是正整數了 { //這裡的相差是絕對值, 特判一下 , if(s % n == 0) printf("1") ; else printf("0") ; } else { search( 0 , 0 ,s) ; printf("%lld", tot) ; } return 0 ; }
【Std】:
/* by : Zmonarch 知識點 :搜尋 */ #include <cstdio> #include <algorithm> #include <cmath> #include <iostream> #include <queue> #include <set> #include <stack> #include <cstring> #define int long long using namespace std ; inline int read() { int x = 0 , f = 1 ; char ch = getchar() ; while(!isdigit(ch)) { if(ch == '-') f = - 1 ; ch = getchar() ; } while( isdigit(ch)) { x = x * 10 + ch - '0' ; ch = getchar() ; } return x * f ; } int n , tot , s , p ; void search(int now , int last ,int rest) { if(now == n) //現在已經加到了最後一個數 { if (abs(rest - last) <= p) tot ++ ; return ; } for(int i = max((long long)1 , last - p) ; i <= min(last + p , rest - n + i); i++)//前一個數和後一個數不能超過p { search(now + 1 , i , rest - i) ; } } signed main() { //freopen("math.in" , "r" , stdin) ; //freopen("math.out" , "w" , stdout) ; n = read() , s = read() , p = read() ; //for(int i = 1 ; i <= s ; i++) if(p == 0) //因為是正整數, 所以如果相差為零, 那麼也就只有一種情況, 那就是全部都是同一個數的時候,除不盡就不是正整數了 { //這裡的相差是絕對值, 特判一下 , if(s % n == 0) printf("1") ; else printf("0") ; } else { for(int i = 1 ; i <= s-(n-1) ; i++) search( 2 , i ,s - i) ; printf("%lld", tot) ; } return 0 ; }
【T2】:
【題目描述】:
給出一個\(n \times n\)的網格,有一些格子是障礙,再給出一對起點終點,求從起點到終點需要的最小步數,每次可以從一個格子走到上下左右4相鄰的四個格子裡.
【輸入】:
第一行一個整數\(n\)。
以下\(n\)行\(n\)個整數,描述整個網格,其中\(0\)表示沒有障礙,\(1\)表示有障礙。
最後一行四個整數,\(Sx,Sy,Tx,Ty\),描述起點和終點。
【輸出】 :
輸出最少步數。
如果永遠走不到輸出-1。
【資料範圍】:
對於30%的資料,\(n<=10\)
對於 100%的測試資料,\(n<=1000\)。
【考場程式碼】:
大水題 ,一眼切 , 直接過。
/*
by : Zmonarch
知識點 : 搜尋
*/
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <queue>
#include <set>
#include <stack>
#include <cstring>
#define int long long
using namespace std ;
const int kmaxn = 1000 + 1 ;
const int inf = 2147483647 ;
inline int read()
{
int x = 0 , f = 1 ; char ch = getchar() ;
while(!isdigit(ch)) { if(ch == '-') f = - 1 ; ch = getchar() ; }
while( isdigit(ch)) { x = x * 10 + ch - '0' ; ch = getchar() ; }
return x * f ;
}
int n , vis[kmaxn][kmaxn] , f[kmaxn][kmaxn] , sx , sy , tx , ty , ans = inf;
int dx[4] = {0 , 0 , 1 , -1} ;
int dy[4] = {1 , -1 , 0 , 0} ;
struct node
{
int x , y , step ;
};
queue<node> q ;
bool check(int x , int y)
{
return ( x <= n && y<=n && x >= 1 && y >= 1) ;
}
void search(node now)
{
q.push(now) ;
while(!q.empty())
{
node u = q.front() ;
q.pop() ;
int x = u.x , y = u.y , step = u.step ;
if(step >= ans) continue ; //小小的優化,截去不符合條件的搜尋枝
if(u.x == tx && u.y == ty)
{
ans = min(ans , step) ;
}
for(int i = 0 ; i < 4 ; i++)
{
int kx = x + dx[i] ;
int ky = y + dy[i] ;
if(!check(kx , ky)) continue ; //檢查邊界
if(vis[kx][ky]) continue ;
vis[kx][ky] = 1 ;
// printf("%d %d\n" , kx , ky) ;
node nxt = {kx , ky , step + 1} ;
q.push(nxt) ;
}
}
}
signed main()
{
//freopen("grid.in" , "r" , stdin) ;
//freopen("grid.out" , "w" , stdout) ;
n = read() ;
for(int i = 1 ; i <= n ; i++)
{
for(int j = 1 ; j <= n ; j++)
{
vis[i][j] = read() ;
}
}
sx = read() , sy = read() , tx = read() , ty = read() ;
if(vis[sx][sy] || vis[tx][ty])
{
cout <<"-1" ;
return 0 ;
}
node ss = {sx , sy , 0} ;
search(ss) ;
if(ans != inf) printf("%lld" , ans) ;
else printf("-1") ;
return 0 ;
}
【T3】
【題目描述】 :
戈蘭斜是一種在帶數字的網格上玩的日本拼圖遊戲。目標是在網格的每個單元格中繪製對角線,連線到每個格點的對角線個數等於他對應的數字。另外,禁止對角線形成環。
第 一個 圖給 出了遊戲的初始狀態。 第二個圖給出了對應的一個解答。資料保證問題一定存在至少一解。
【輸入】:
輸 入的 第一 行包含一個的單個整數 \(n\)表示棋盤的尺寸,棋盤是一個正方形。
然後緊接 \(n+1\)行。包含網格的初始狀態。每行為一個含\(n+1\)個字元的字串,字元要麼為一個數字,要麼為一個(‘.’),
其中數字都是\(0\)到\(4\)之間的任意整數,‘.’表示連線到此格點的對角線數沒有限制
【輸出】:
輸出包含 \(n\)行,每行 \(n\) 個字元,每個字元為斜槓或反斜槓表示如何填充相應的棋盤。
【資料範圍】 :
對於 \(100%\)的資料 , \(n\leq 7\)