제출 #1271098

#제출 시각아이디문제언어결과실행 시간메모리
1271098nthvn은행 (IZhO14_bank)C++20
100 / 100
598 ms11864 KiB
#include "bits/stdc++.h"
using namespace std;

#define fi first
#define se second
#define pii pair<int,int> 
#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()
#define pb push_back
#define ll long long

signed main(){
	ios_base::sync_with_stdio(NULL);
	cin.tie(NULL);
	// Thay đổi tên file cho đúng với đề bài
	if(fopen("bank.in", "r")){
		freopen("bank.in", "r", stdin);
		freopen("bank.out", "w", stdout);
	}
	
	int n, m;
	cin >> n >> m;
	
	vector<int> a(n); // Mảng lương của N người
	for(int i = 0; i < n; ++i) {
		cin >> a[i];
	}
	
	vector<int> b(m); // Mảng giá trị của M tờ tiền
	for(int i = 0; i < m; ++i) {
		cin >> b[i];
	}
	
	// --- Bước 1: Tiền xử lý tính tổng của mọi tập con tờ tiền ---
	// Map một tổng tiền tới danh sách các mặt nạ bit (tập tiền) có tổng đó
	map<int, vector<int>> sum_to_masks;
	for (int mask = 0; mask < (1 << m); ++mask) {
		ll current_sum = 0;
		for (int i = 0; i < m; ++i) {
			if ((mask >> i) & 1) { // Nếu tờ tiền thứ i có trong tập
				current_sum += b[i];
			}
		}
		if (current_sum <= 1000 * 20) { // Giới hạn tổng để tránh tràn map
		    sum_to_masks[current_sum].push_back(mask);
		}
	}
	
	// --- Bước 2: Quy hoạch động ---
	// dp[mask] = mặt nạ các tờ tiền dùng để trả cho tập người trong `mask`
	// Khởi tạo dp với -1 (trạng thái không thể đạt tới)
	vector<int> dp(1 << n, -1);
	
	// Trạng thái cơ sở: không trả cho ai thì không tốn tờ tiền nào
	dp[0] = 0; 
	
	// Duyệt qua tất cả các mặt nạ của tập người
	for (int mask_nguoi = 0; mask_nguoi < (1 << n); ++mask_nguoi) {
		// Nếu trạng thái hiện tại không thể đạt tới, bỏ qua
		if (dp[mask_nguoi] == -1) {
			continue;
		}
		
		// Thử trả lương cho một người `i` chưa được trả
		for (int i = 0; i < n; ++i) {
			// Nếu người i đã có trong mask_nguoi, bỏ qua
			if ((mask_nguoi >> i) & 1) {
				continue;
			}
			
			int luong_can_tra = a[i];
			
			// Kiểm tra xem có tập tiền nào có tổng bằng luong_can_tra không
			if (sum_to_masks.count(luong_can_tra)) {
				// Duyệt qua các tập tiền có thể trả được lương này
				for (int mask_tien_tra_luong : sum_to_masks[luong_can_tra]) {
					// Kiểm tra xem tập tiền này có chung tờ nào với tập đã dùng không
					if ((dp[mask_nguoi] & mask_tien_tra_luong) == 0) {
						// Nếu không chung, ta tìm được một cách trả lương hợp lệ
						int mask_nguoi_moi = mask_nguoi | (1 << i);
						int mask_tien_moi = dp[mask_nguoi] | mask_tien_tra_luong;
						
						// Cập nhật trạng thái mới. 
						// Chỉ cần tìm được 1 cách là đủ.
						if (dp[mask_nguoi_moi] == -1) {
						    dp[mask_nguoi_moi] = mask_tien_moi;
						}
					}
				}
			}
		}
	}
	
	// --- Bước 3: Kiểm tra kết quả ---
	// Nếu dp[(1<<n) - 1] khác -1, nghĩa là có cách trả lương cho tất cả mọi người
	if (dp[(1 << n) - 1] != -1) {
		cout << "YES\n";
	} else {
		cout << "NO\n";
	}
	
	return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

bank.cpp: In function 'int main()':
bank.cpp:17:24: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   17 |                 freopen("bank.in", "r", stdin);
      |                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
bank.cpp:18:24: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   18 |                 freopen("bank.out", "w", stdout);
      |                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...