উত্তর:
বেশ ব্যবহারিক পদ্ধতির বিদ্যমান যে কাজ সময়, যেখানে প্রসেসর শব্দ বিট সংখ্যা। মূল ধারণাটি হ'ল আপনি ক্রমবর্ধমান ক্রমে ম্যাট্রিক্সের উপাদানগুলির উপর একের পর এক পুনরাবৃত্তি করুন (নির্বিচারে সম্পর্ক ছিন্ন করুন) এবং "তাদের স্যুইচ করুন"। এই মুহুর্তটি বিবেচনা করুন যখন কিছু ট্রিপল of স্যুইচ করা থাকে। সরলতার জন্য, এর অনুমান করা বলল উপাদান যে দিন । শেষ উপাদানটি চালু করা হলে এখনই উত্তরে ট্রিপলের মান যুক্ত হওয়া স্বাভাবিক। সুতরাং আমাদের সম্ভাব্য এর সংখ্যা গণনা করতে হবে এবংইতিমধ্যে চালু আছে (এটি ত্রিপের সংখ্যা হবে, এখানে the সর্বাধিক উপাদান, সুতরাং সেগুলি এখনই পুরোপুরি স্যুইচ করা হয়েছিল)। এখানে আমরা বিট অপ্টিমাইজেশান ব্যবহার করে নিষ্পাপ বাস্তবায়নকে গতিময় করতে পারি ।
বিশদের জন্য আপনি সি ++ 11 এ নিম্নলিখিত প্রয়োগগুলি উল্লেখ করতে পারেন যা , জন্য কাজ করা উচিত (এটি খুব অনুকূল নয়; তবে এটি এখনও কমপক্ষে আমার মেশিনে বৃহত্তর মার্জিন দ্বারা জন্য পরাজিত করে)।
// code is not very elegant,
// but should be understandable
// here the matrix a has dimensions n x n
// a has to be symmetric!
int64_t solve (int n, const vector<vector<int32_t>> &a)
{
std::vector<boost::dynamic_bitset<int64_t>> mat
(n, boost::dynamic_bitset<int64_t>(n));
vector<pair<int, int>> order;
for (int j = 1; j < n; j++)
for (int i = 0; i < j; i++)
order.emplace_back(i, j);
sort(order.begin(), order.end(),
[&] (const pair<int, int> &l, const pair<int, int> &r)
{return a[l.first][l.second] < a[r.first][r.second];});
int64_t ans = 0;
for (const auto &position : order)
{
int i, j;
tie (i, j) = position;
mat[i][j] = mat[j][i] = 1;
// here it is important that conditions
// mat[i][i] = 0 and mat[j][j] = 0 always hold
ans += (mat[i] & mat[j]).count() * int64_t(a[i][j]);
}
return ans;
}
যদি আপনি বিট অপটিমাইজেশন প্রতারণামূলক ব্যবহার বিবেচনা করে থাকেন তবে আপনি এখানে একই ফলাফলের জন্য চারটি রুশিয়ান পদ্ধতি ব্যবহার করতে পারেন, একটি এলগরিদম উপস্থাপন করতে পারেন যা কম ব্যবহারিক হওয়া উচিত (কারণ বেশিরভাগ আধুনিক হার্ডওয়্যারে বেশ বড়) তাত্ত্বিকভাবে ভাল। প্রকৃতপক্ষে, আসুন এবং ম্যাট্রিক্সের প্রতিটি সারি 0 পূর্ণসংখ্যার থেকে পর্যন্ত রাখি , যেখানে তম সংখ্যাটি রয়েছে অ্যারে টির মধ্যে একচেটিয়া সমেত সারিটির বিটগুলির সাথে মিলে যায়-indexation। আমরা সময়ে এই জাতীয় দুটি ব্লকের স্কেলার পণ্যগুলি পূর্বনির্ধারণ করতে পারি । ম্যাট্রিক্সে একটি অবস্থান আপডেট করা দ্রুত কারণ আমরা কেবল একটি পূর্ণসংখ্যা পরিবর্তন করছি। সারিগুলির স্কেলার পণ্যটি অনুসন্ধান করতে এবং কেবল সারিগুলির সাথে সম্পর্কিত অ্যারেগুলিতে পুনরাবৃত্তি করুন, সারণীতে সংশ্লিষ্ট ব্লকের স্কেলার পণ্যগুলি সন্ধান করুন এবং প্রাপ্ত পণ্যগুলি যোগ করুন।
উপরের অনুচ্ছেদ পূর্ণসংখ্যার সঙ্গে যে অপারেশন অনুমান নেওয়া সময়। এটি বেশ সাধারণ অনুমান , কারণ এটি সাধারণত অ্যালগরিদমের তুলনামূলক গতি পরিবর্তন করে না (উদাহরণস্বরূপ, আমরা যদি এই অনুমানটি ব্যবহার না করি তবে ব্রুটি ফোর্স পদ্ধতিটি আসলে সময়ে কাজ করে (এখানে আমরা বিট ক্রিয়াকলাপগুলিতে সময় পরিমাপ করি) যদি some কিছু ধ্রুবক জন্য কমপক্ষে to পর্যন্ত পূর্ণ মানগুলির সাথে পূর্ণসংখ্যার মানগুলি গ্রহণ করি (এবং অন্যথায় আমরা দিয়ে সমস্যাটি সমাধান করতে পারি) যাইহোক ম্যাট্রিক্সের গুণগুলি); তবে উপরের চারটি রুশিয়ান পদ্ধতি ব্যবহারের জন্য প্রস্তাবিত সেই ক্ষেত্রে আকারের সংখ্যার ক্রিয়াকলাপ ; সুতরাং এটি বিট অপারেশন করে, যা মডেল পরিবর্তন সত্ত্বেও ব্রুট ফোর্সের চেয়ে ভাল)
পদ্ধতির অস্তিত্ব সম্পর্কে প্রশ্নটি এখনও আকর্ষণীয়।
এই উত্তরে উপস্থাপিত কৌশলগুলি (বিট অপটিমাইজেশন এবং চারটি রুশিয়ান পদ্ধতি) কোনওভাবেই আসল নয় এবং প্রকাশের সম্পূর্ণতার জন্য এখানে উপস্থাপন করা হয়েছে। তবে এগুলি প্রয়োগ করার উপায় খুঁজে পাওয়া তুচ্ছ নয়।
mat[i]
mat[j]
mat
যা গুরুত্বপূর্ণ বলে মনে হচ্ছে। আমি বুঝতে পারি যে এটি কীভাবে সংজ্ঞায়িত করা যেতে পারে তবে আমি অবাক হয়েছি যে (mat[i] & mat[j]).count()
কোনও এসটিএল ধারক দিয়ে কাঙ্ক্ষিত কাজ করবে কিনা ।
mat
- আমার ধারণা আমাদের অবশ্যই ব্যবহার করা উচিত std::vector<boost::dynamic_bitset<int64_t>>
।
mat
: হ্যাঁ, আমার মনে আসলে স্ট্যান্ডার্ড বিটসেট ছিল তবে boost::dynamic_bitset
এটি ক্ষেত্রে আরও ভাল, কারণ এর আকারটি সংকলন-সময় ধ্রুবক হতে হবে না। এই বিশদটি যুক্ত করতে এবং চারটি রুশিয়ান পদ্ধতির ব্যাখ্যা করতে উত্তরটি সম্পাদনা করবে।