AT_future_contest_2019_final_b ビジュアライザ
题目描述
[problemUrl]: https://atcoder.jp/contests/future-contest-2019-final/tasks/future_contest_2019_final_b
输入格式
无
输出格式
无
说明/提示
### 测试用例生成
我们提供了指定随机种子并在本地生成测试用例的功能。
- 本功能假定在 Chrome 浏览器上运行。无法保证在其他环境下能正常工作,尤其是在 IE 上已确认无法运行。
- 本功能不保证与本次竞赛中的测试用例完全一致。特别是随机数生成的实现可能存在差异,请提前知晓。
- 种子 =
### 可视化工具
我们提供了一个可视化工具,可以根据输入文件和输出文件计算分数并可视化结果。
- 本可视化工具假定在 Chrome 浏览器上运行。无法保证在其他环境下能正常工作,尤其是在 IE 上已确认无法运行。
- 本可视化工具无法提交解答。请在 AtCoder A 问题“モンスターテイマー”页面提交解答。
- 本可视化工具计算的分数不保证与竞赛中的分数一致。因使用本可视化工具造成的任何损失,恕不负责,请提前知晓。
输入文件:
输出文件:
▶ 播放速度:慢快
回合
たかはしくん 正在渴望成为你的伙伴!
分数
0
金钱
0
技能
※显示的怪兽形象仅为示意,对分数无影响。
const MAX_LEVEL = 10;
const APPANAGE = 1000;
const COST_TRAINING = 10000;
var inputFlg = false;
var loadedFlg = false;
var T = 1000;
var N = 10;
var M = 30000;
var rendTurn = 0;
var tasks = [];
var outputData = [];
var order = [];
var golds = [];
var skills = [];
var trainings = [];
var done = []
var mosterType = []
var invalidQuests = []
var doneQuests = []
class Task{
constructor(inputStr){
this.start = Number(inputStr[0]);
this.end = Number(inputStr[1]);
this.gold = Number(inputStr[2]);
this.takes = [...Array(N)].map(() => 0);
for(var i=0; i < N; i++){
this.takes[i] = Number(inputStr[3 + i]);
}
this.done = false;
}
output(){
ret = start + "-" + end + " \\" + gold + " \[" + takes[0];
for(var i; i < N; i++){
ret += +","+takes[i];
}
ret += "\]"
return ret;
}
}
class Order{
constructor(inputStr){
this.type = Number(inputStr[0]);
if(this.type == 1 || this.type == 2){
this.param = Number(inputStr[1]);
}
}
output(){
ret = this.type;
if(type == 1 || type == 2){
ret += "-" + this.param;
}
return ret;
}
}
// 测试用例生成
$("#createTestCase").click(function() {
let seed = $('#testCaseSeed').val();
if (!isFinite(seed) || Number(seed) < 0 || !seed){
seed = 0;
$('#testCaseSeed').val(seed);
}
console.log("seed="+seed);
const random = new Random(seed);
records = "1000 10 30000\r\n";
var quests = [];
var questType = [0,1,2];
var L = 0;
for (var i = 0; i < 30000; i++) {
switch(questType[random.nextInt(0, 2)]){
case 0:
L = random.nextInt(2, 10);
break;
case 1:
L = random.nextInt(11, 100);
break;
case 2:
L = random.nextInt(101, 1000);
break;
default:
console.log("Error!");
return;
}
var A = random.nextInt(1, Math.max(1,1000 - L));
var B = A + L - 1;
var takes = [...Array(10)].map(() => 0);
takes[0] = random.nextInt(1, 10);
for(var j = 1; j < 10; j++){
takes[j] = random.nextInt(0, takes[j-1]);
}
// 洗牌
for(var j = 10 - 1; j > 0; j--){
var r = Math.floor(random.nextDouble() * (j + 1));
var tmp = takes[j];
takes[j] = takes[r];
takes[r] = tmp;
}
var sum = takes.reduce((a,x) => a+=x,0);
var C = Math.floor(sum * 1.3 * random.nextInt(1,2000 ));
records += A + " " + B + " " + C;
for(var j = 0; j < 10; j++){
records += " " + takes[j];
}
records += "\r\n";
}
var blob = new Blob([records], {
"type": "text/plain"
});
window.URL = window.webkitURL || window.URL; $("#download").attr("href", window.URL.createObjectURL(blob));
document.getElementById('download').innerText = "Input_" + seed;
let fileName = "testCase_" + seed + ".txt";
$('#download').attr('download', fileName);
});
class Random {
constructor(seed = 88675123){
this.x = 123456789;
this.y = 362436069;
this.z = 521288629;
this.w = seed;
}
// XorShift
next() {
let t;
t = this.x ^ (this.x >> 19)) ^ (t ^ (t >>> 8));
}
nextInt(min, max) {
const r = Math.abs(this.next());
return min + (r % (max + 1 - min));
}
nextDouble() {
const r = Math.abs(this.next());
return (r % (1000000007 + 1)) / 1000000007;
}
};
// 输入文件读取
var handleInputFiles = function (file, callback) {
document.getElementById('inputFile').innerText = '';
document.getElementById('outputFile').innerText = ''; $('#output').val('');
inputFlg = false;
loadedFlg = false;
document.getElementById('score').innerText = 0;
var reader = new FileReader();
reader.readAsText(file[0]);
reader.onload = function (ev) {
const inputDatalist = reader.result.split(/\r\n|\r|\n/);
if(inputDatalist.length < 1){
console.log("No Text Error!! " + inputDatalist.length);
document.getElementById('inputFile').innerText = 'error!';
$('#input').val('');
return;
}
var firstLine = inputDatalist[0].split(" ");
if(firstLine.length != 3){
console.log("First Line Error!! " + inputDatalist.length);
document.getElementById('inputFile').innerText = 'error!'; $('#input').val('');
return;
}
for(var i = 0; i < 3; i++){
if(Number.isNaN(Number(firstLine[i]))){
console.log("First Line Error!! " + inputDatalist.length);
document.getElementById('inputFile').innerText = 'error!';
$('#input').val('');
return;
}
}
T = Number(firstLine[0]);
N = Number(firstLine[1]);
M = Number(firstLine[2]);
tasks = [...Array(M)].map(() => null);
if(inputDatalist.length < M){
console.log("T Error!! " + inputDatalist.length);
document.getElementById('inputFile').innerText = 'error! short line!'; $('#input').val('');
return;
}
for (var i = 0; i < M; i++) {
line = inputDatalist[i+1].split(" ");
if(line.length < 3 + N){
console.log("M error!! " + (i+1) + " " +inputDatalist[i].length);
console.log(inputDatalist[i]);
document.getElementById('inputFile').innerText = 'error! invalid task!';
$('#input').val('');
return;
}
for (var j = 0; j < 3 + N; j++) {
if(Number.isNaN(Number(line[j]))){
document.getElementById('inputFile').innerText = 'error! not number!';
console.log("type error!! Line=" + i); $('#input').val('');
return;
}
if(Number(line[j]) < 0){
document.getElementById('inputFile').innerText = 'error! negative value!';
console.log("negative value error!! Line=" + i);
$('#input').val('');
return;
}
if(j < 3){
continue;
}
if(Number(line[j]) > MAX_LEVEL){
document.getElementById('inputFile').innerText = 'error! over level 10!';
console.log("over level error!! Line=" + i); $('#input').val('');
return;
}
}
tasks[i] = new Task(line);
}
document.getElementById('inputFile').innerText = 'OK!';
console.log("input OK!");
inputFlg = true;
setTimeout(function() {
callback(-1);
}, 50);
};
}
function clearInFilePath() {
$('#input').val('');
}
function clearOutFilePath() { $('#output').val('');
}
// 输出文件读取
function handleOutputFiles(file, callback) {
document.getElementById('outputFile').innerText = '';
if (!inputFlg) {
document.getElementById('outputFile').innerText = 'input first!';
$('#output').val('');
return;
}
loadedFlg = false;
outputData = [];
document.getElementById('score').innerText = 0;
var reader = new FileReader();
reader.readAsText(file[0]);
reader.onload = function (ev) {
const outputDatalist = reader.result.split(/\r\n|\r|\n/);
if(outputDatalist.length < T){
console.log("output filr error!");
document.getElementById('outputFile').innerText = 'error! short line!'; $('#output').val('');
return;
}
order = [...Array(T)].map(() => null);
for (var i = 0; i < T; i++) {
line = outputDatalist[i].split(" ");
if(Number.isNaN(Number(line[0]))){
console.log("output filr error! Line=" + i);
console.log(row);
document.getElementById('outputFile').innerText = 'error! not number!';
$('#output').val('');
return;
}
switch(Number(line[0])){
case 1:
if(line.lengh < 2){
console.log("output filr error! Line=" + i);
document.getElementById('outputFile').innerText = 'error! needs second param!'; $('#output').val('');
return;
}
if(Number.isNaN(Number(line[1]))){
console.log("output filr error! Line=" + i);
console.log(row);
document.getElementById('outputFile').innerText = 'error! not number!';
$('#output').val('');
return;
}
if(Number(line[1]) > MAX_LEVEL || Number(line[1]) < 1){
console.log("output filr error! Line=" + i);
document.getElementById('outputFile').innerText = 'error! invalid skill no!'; $('#output').val('');
return;
}
order[i] = new Order(line);
break;
case 2:
if(line.lengh < 2){
console.log("output filr error! Line=" + i);
document.getElementById('outputFile').innerText = 'error! needs second param!';
$('#output').val('');
return;
}
if(Number.isNaN(Number(line[1]))){
console.log("output filr error! Line=" + i);
console.log(row);
document.getElementById('outputFile').innerText = 'error! not number!'; $('#output').val('');
return;
}
if(Number(line[1]) > M || Number(line[1]) < 1){
console.log("output filr error! Line=" + i);
document.getElementById('outputFile').innerText = 'error! invalid task no!';
$('#output').val('');
return;
}
order[i] = new Order(line);
break;
case 3:
order[i] = new Order(line);
break;
default:
document.getElementById('outputFile').innerText = 'error! not 1 or 2 or 3!';
console.log("output filr error! Line=" + i);
console.log("error!!"); $('#output').val('');
return;
}
}
document.getElementById('outputFile').innerText = 'OK!';
console.log("output OK!");
loadedFlg = true;
setTimeout(function() {
simulate();
callback(T+1);
}, 50);
};
}
function simulate() {
if(!inputFlg || ! loadedFlg){
return;
}
// 初始化
done = [...Array(M)].map(() => false);
skills = [...Array(T+1)].map(() => [...Array(N)].map(() => 0));
trainings = [...Array(T+1)].map(() => [...Array(N)].map(() => 0));
golds = [...Array(T+1)].map(() => 0);
golds[0] = 1000;
mosterType = [...Array(T+1)].map(() => "m1");
invalidQuests = [...Array(T+1)].map(() => false);
doneQuests = [...Array(T+1)].map(() => false);
for (var i = 0; i < T; i++) {
// 复制
for(var j = 0; j < N; j++) {
skills[i+1][j] = skills[i][j];
trainings[i+1][j] = trainings[i][j];
}
mosterType[i+1] = mosterType[i];
var nowGold = golds[i];
var nowOrder = order[i];
switch(nowOrder.type){
case 1:
var skillNo = nowOrder.param-1;
if(skills[i][skillNo] >= MAX_LEVEL){
break;
}
var nextLevel = skills[i][skillNo] + 1;
if(nowGold < Math.pow(2,nextLevel) * COST_TRAINING){
break;
}
nowGold -= Math.pow(2,nextLevel) * COST_TRAINING;
trainings[i+1][skillNo]++;
if(trainings[i+1][skillNo] >= nextLevel){
trainings[i+1][skillNo]=0;
skills[i+1][skillNo]++;
var sum = 0;
for(var j = 0; j < N; j++) {
sum += skills[i+1][j];
}
switch(sum){
case 10:
mosterType[i+1] = "m2-a"
for(var j = 0; j < N; j++) {
if(skills[i+1][j]>1){
mosterType[i+1] = "m2-b"
break;
}
}
break;
case 20:
mosterType[i+1] = "m3-a"
for(var j = 0; j < N; j++) {
if(skills[i+1][j]>2){
mosterType[i+1] = "m3-b"
break;
}
}
break;
case 30:
mosterType[i+1] = "m4-a"
for(var j = 0; j < N; j++) {
if(skills[i+1][j]>3){
mosterType[i+1] = "m4-b"
break;
}
}
break;
case 50:
mosterType[i+1] = "m5-a"
for(var j = 0; j < N; j++) {
if(skills[i+1][j]>5){
mosterType[i+1] = "m5-b"
break;
}
}
break;
case 70:
mosterType[i+1] = "m6-a"
for(var j = 0; j < N; j++) {
if(skills[i+1][j]>7){
mosterType[i+1] = "m6-b"
break;
}
}
break;
case 90:
mosterType[i+1] = "m7-a"
for(var j = 0; j < N; j++) {
if(skills[i+1][j]>9){
mosterType[i+1] = "m7-b"
break;
}
}
break;
case 100:
mosterType[i+1] = "m8"
break;
default:
break;
}
}
break;
case 2:
var task = tasks[nowOrder.param-1];
if(task.start > i+1 || task.end < i+1){
invalidQuests[i] = true;
break;
}
if(done[nowOrder.param-1]){
doneQuests[i] = true;
break;
}
money = task.gold;
money *= (1 + 9 * (i+1 - task.start) / (task.end - task.start));
skillLack = 0;
for (var j = 0; j < N; j++){
skillLack += Math.max(0, task.takes[j] - skills[i][j]);
}
if (skillLack == 0){
money *= 10;
} else {
money *= Math.pow(0.5, skillLack);
money += 1e-9;
}
nowGold += Math.floor(money);
done[nowOrder.param-1] = true;
break;
case 3:
nowGold += APPANAGE;
break;
default:
document.getElementById('outputFile').innerText = 'error! not 1 or 2 or 3!';
console.log("output filr error! Line=" + i);
console.log("error!!");
$('#output').val('');
return;
}
golds[i + 1] = nowGold;
var str = i + " " + nowGold + " [";
for(var j = 0; j < N; j++){
str += skills[i+1][j] + ",";
}
str += "]";
//console.log(str);
}
document.getElementById('score').innerText = golds[T];
}
function wrongAnswer(str, t) {
console.log("simulate error!! turn="+ t + " " + str);
outputData = [];
_isRunning = false;
start.innerText = '▶';
render(t);
document.getElementById('slider1o').value = t;
document.getElementById('outputFile').innerText = 'error!';
document.getElementById('score').innerText = 'WA';
}
var render = function(rendTurn) {
this.rendTurn = rendTurn;
if(!inputFlg){
return;
}
if(rendTurn < 0){
document.getElementById('money').innerText = 0;
return;
}
if(!loadedFlg){
return;
}
if(rendTurn >= T){
document.getElementById('money').innerText = golds[T];
document.getElementById('message-area').innerHTML =
"你获得了"+golds[T]+ " 日元!";
for(var i = 0;i < N;i++){
myChart.chart.data.datasets[0].data[i] = skills[T][i];
}
myChart.chart.update();
document.getElementById("monster").className = mosterType[T];
return;
}
document.getElementById('money').innerText = golds[rendTurn];
for(var i=0;i T + 2){
_isRunning = false;
start.innerText = '▶';
cancelAnimationFrame(_animationID);
output.value = 0;
return;
}
_animationID = requestAnimationFrame(autoUpdate);
frame++;
if(frame % (50 - Number(animeSpeed.value)) !== 0){ return; }
render(Number(output.value));
output.value = tmp;
value = tmp;
set_value();
}
// 开始按钮点击
start.onclick = function(evt){
if (_isRunning) {
_isRunning = false;
start.innerText = '▶';
cancelAnimationFrame(_animationID);
} else if(loadedFlg){
_isRunning = true;
start.innerText = '■';
autoUpdate();
} else {
if(inputFlg && order.length == T+1){ $('#input').val('');
$('#output').val('');
if(loadedFlg){
_isRunning = true;
start.innerText = '■';
autoUpdate();
}
}
}
};
// 点击刻度部分
slider.onclick = function(evt){
dragging = true;
document.onmousemove(evt);
document.onmouseup();
};
// 数值变更
output.onchange = function(evt){
value = evt.target.value;
render(Number(evt.target.value));
};
// 拖拽开始
input.onmousedown = function(evt){
dragging = true;
return false;
};
// 拖拽结束
document.onmouseup = function(evt){
if (dragging) {
dragging = false;
output.value = value;
render(value);
}
};
document.onmousemove = function(evt){
if(dragging){
// 拖拽中
if(!evt){
evt = window.event;
}
var left = evt.clientX;
var rect = slider.getBoundingClientRect();
// 根据鼠标坐标和滑块位置决定值
value = Math.round(left - rect.left - width);
// 超出滑块范围
if (value < 0) {
value = 0;
} else if (value > slider.clientWidth) {
value = slider.clientWidth;
}
set_value();
return false;
}
};
})();
// 颜色设置
var colorSet = {
red: 'rgb(255, 99, 132)',
orange: 'rgb(255, 159, 64)',
yellow: 'rgb(255, 205, 86)',
green: 'rgb(75, 192, 192)',
blue: 'rgb(54, 162, 235)',
purple: 'rgb(153, 102, 255)',
grey: 'rgb(201, 203, 207)'
};
// 颜色RGB转换
var color = Chart.helpers.color;
/*
* 图表初始设置
*/
var config = {
type: 'radar',
data: {
labels: ["No.1", "No.2", "No.3", "No.4", "No.5", "No.6", "No.7", "No.8", "No.9", "No.10"],
datasets: [{
label: "等级",
backgroundColor: color(colorSet.blue).alpha(0.5).rgbString(),
borderColor: colorSet.blue,
pointBackgroundColor: colorSet.blue,
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},]
},
options: {
chartArea: {
backgroundColor: "#000"
},
animation: {
duration: 1500,
},
maintainAspectRatio: false,
showTooltips: false,
responsive: false,
legend: {
display: false
},
title: {
display: false
},
scale: {
display: true,
pointLabels: {
fontSize: 10,
fontColor: colorSet.yellow
},
gridLines: {
display: true,
color: colorSet.yellow
},
ticks: {
display: false,
fontColor: "#FFF",
fontSize: 8,
min: 0,
max: 10
}
}
}
};
var myChart = new Chart( $("#skill-chart"), config);
由 ChatGPT 4.1 翻译