What you can do is treat it as a many-to-many join between two tables, Voters and Issues. The relationship is usually addressed with a third table, in this case Vote (or Ballet if it reduces confusion).
In summary, push Voters and Issues into tables (arrays, or mappings with indexes). Some patterns here: Are there well-solved and simple storage patterns for Solidity?
Pick a pattern that lets you easily confirm a Voter is actually registered and an Issue actually exists. Then hash the keys and push a Vote into the Vote table.
By "table" I mean one of the constructs described in the above-linked answer. Think about the strengths a weaknesses and choose accordingly. For the votes themselves, I would consider:
struct Vote {
bool yayNay;
bool isVote;
}
mapping(she3HashKey => Vote) voteStructs;
The second field would be set to true for all votes cast so you can tell a real "false" from a default 0, because ...
In my approach, you need simple functions to check if things exist:
isVoter() public constant returns(bool isIndeed) {}
isIssue() public constant returns(bool isIndeed) {}
isVote() public constant returns(bool isIndeed) {}
That's a must or you might get tangled up in awkward problems, e.g. differentiating a default (false) from an actual "Nay".
Check the first two before you allow a new Vote.
if(!isVoter(msg.sender)) throw;
if(!isIssue(issueId)) throw;
// continue ...
Check the third one before you do anything with a stored Vote.
Keep your tallies as you go so you can avoid iteration at all costs.
Hope it helps.