在使用 C# 语言解 ACM 题的时候,如果能够有一个 ReadInt32 方法直接从标准输入读取整数比较方便的。下面就是一个 I/O 助手类 IOHelper:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | namespace Skyiv { using System; using System.IO; using System.Text; sealed class IOHelper : IDisposable { static readonly Encoding Encoding = Encoding.ASCII; // or UTF8 ? static readonly byte [] EOLS = Encoding.GetBytes(Environment.NewLine); static readonly byte [] BLANKS = { 9, 10, 13, 32 }; // tab,lf,cr,space static readonly byte EOF = 0; // assume '\0' not in input file byte [] buf = new byte [32]; // for Write(int n) byte [] buffer = new byte [64 * 1024]; int current = 0; int count = 0; BinaryReader reader; BinaryWriter writer; public IOHelper() : this (Console.OpenStandardInput(), Console.OpenStandardOutput()) {} public IOHelper(Stream reader, Stream writer) { this .reader = new BinaryReader(reader); this .writer = new BinaryWriter(writer); } byte ReadByte() { if (current >= count) { count = reader.Read(buffer, current = 0, buffer.Length); if (count == 0) return EOF; } return buffer[current++]; } public static byte [] GetBytes( string str) { return Encoding.GetBytes(str); } public int ReadInt32() { var n = 0; var ok = false ; for ( byte b; (b = ReadByte()) != EOF; ) { if (Array.IndexOf(BLANKS, b) >= 0) if (ok) break ; else continue ; n = n * 10 + (b - '0' ); ok = true ; } return n; } public int ReadLine( byte [] buffer) { var n = 0; while (n < buffer.Length) { var b = ReadByte(); if (b == EOLS[0]) { if (EOLS.Length == 2 && ReadByte() != EOLS[1]) throw new InvalidDataException( "Invalid EOL" ); break ; } buffer[n++] = b; } return n; } public void Write( int n) { if (n == 0) { writer.Write(( byte ) '0' ); return ; } var i = buf.Length; for (; n > 0; n /= 10) buf[--i] = ( byte )((n % 10) + '0' ); Write(buf, i, buf.Length - i); } public void Write( byte [] buffer, int index, int count) { writer.Write(buffer, index, count); } public void Write( string str) { var buffer = Encoding.GetBytes(str); writer.Write(buffer, 0, buffer.Length); } public void WriteSpace() { writer.Write(BLANKS, 3, 1); } public void WriteLine() { writer.Write(EOLS, 0, EOLS.Length); } public void Dispose() { if (reader != null ) reader.Close(); if (writer != null ) writer.Close(); } } } |
此外,IOHelper 类还提供以下方法用于处理字符串:
- public int ReadLine(byte[] buffer)
- public void Write(byte[] buffer, int index, int count)
类似于 C/C++ 语言,这两个方法仅仅把字符串当作字节数组处理,使用 ASCII 码。而不是象 C# 语言中字符串是使用 Unicode 进行编码。
下面是一个使用示例,题目来源请参见“I-Keyboard”这篇随笔。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | namespace Skyiv.Ben.Acm { using System; // http://www.spoj.pl/problems/IKEYB/ sealed class Ikeyb { const int MAX = 90; static int [,] cost = new int [MAX + 1, MAX + 1]; static int [,] price = new int [MAX + 1, MAX + 1]; static int [,] index = new int [MAX + 1, MAX + 1]; static int [] F = new int [MAX]; static byte [] keys = new byte [MAX]; static byte [] letters = new byte [MAX]; static byte [] message1 = IOHelper.GetBytes( "Keypad #" ); static byte [] message2 = IOHelper.GetBytes( ": " ); static IOHelper helper; static void Main() { using (helper = new IOHelper()) { var runner = new Ikeyb(); var T = helper.ReadInt32(); for ( var n = 1; n <= T; n++) runner.Run(n); } } void Run( int n) { var K = helper.ReadInt32(); var L = helper.ReadInt32(); helper.ReadLine(keys); helper.ReadLine(letters); for ( var i = 0; i < L; i++) F[i] = helper.ReadInt32(); Initialize(K, L); Compute(K, L); helper.Write(message1, 0, message1.Length); helper.Write(n); helper.Write(message2, 0, 1); helper.WriteLine(); Output(K, L); helper.WriteLine(); } void Initialize( int K, int L) { for ( var i = 0; i <= K; i++) for ( var j = 1; j <= L; j++) price[i, j] = int .MaxValue / 2; for ( var i = 1; i <= L; i++) for ( var j = i; j <= L; j++) cost[i, j] = cost[i, j - 1] + (j - i + 1) * F[j - 1]; } void Compute( int K, int L) { for ( var i = 1; i <= K; i++) for ( var j = i; j <= L; j++) for ( var n = 1; n <= j - i + 1; n++) { var sum = price[i - 1, j - n] + cost[j - n + 1, j]; if (sum <= price[i, j]) { price[i, j] = sum; index[i, j] = n; } } } void Output( int K, int L) { if (K == 0) return ; var n = index[K--, L]; Output(K, L - n); helper.Write(keys, K, 1); helper.Write(message2, 0, message2.Length); helper.Write(letters, L - n, n); helper.WriteLine(); } } } |
如果给出以下输入:
1 2 5 *# ABCDE 1024 32768 2147483647 987 654321
上述程序将产生以下输出:
Keypad #1: *: ABCD #: E
注意上述输出其实是有问题的,正确的输出应该分为 AB 和 CDE 两组。但是程序本身是没有问题的,而是输入数据有问题。因为原来的题目中限定各个字母出现的频率不能超过 100000。
分类:
算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述